MILESTONE 3: PJSIP Wrapper JNI completo y funcionando

This commit is contained in:
2025-11-03 10:58:02 -04:00
parent 31ffabe6cc
commit 9e5d0d8ebf
17865 changed files with 118001 additions and 1963586 deletions

1
GSMGateway/app/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,67 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.gqlabs.gsmgateway"
compileSdk = 35
defaultConfig {
applicationId = "com.gqlabs.gsmgateway"
minSdk = 26
targetSdk = 35
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
ndk {
abiFilters.add("arm64-v8a")
}
externalNativeBuild {
cmake {
cppFlags("-std=c++17")
arguments("-DANDROID_STL=c++_shared")
}
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
externalNativeBuild {
cmake {
path("src/main/cpp/CMakeLists.txt")
version = "3.22.1"
}
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}

21
GSMGateway/app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,24 @@
package com.gqlabs.gsmgateway
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.gqlabs.gsmgateway", appContext.packageName)
}
}

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Permisos necesarios para PJSIP -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<!-- Permisos para llamadas telefónicas (para futuro) -->
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS"/>
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.GSMGateway"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,99 @@
cmake_minimum_required(VERSION 3.22.1)
project("gsmgateway")
add_definitions(
-DPJ_AUTOCONF=1
-DPJ_IS_LITTLE_ENDIAN=1
-DPJ_IS_BIG_ENDIAN=0
)
# Configurar C++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Incluir headers de PJSIP
include_directories(
${CMAKE_SOURCE_DIR}
)
# Biblioteca nativa principal
add_library(gsmgateway SHARED
native-lib.cpp
pjsip_wrapper.c
)
# Variables para simplificar rutas
set(PJSIP_LIBS_DIR ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
# Importar todas las bibliotecas PJSIP como estáticas
add_library(pj STATIC IMPORTED)
set_target_properties(pj PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpj-aarch64-unknown-linux-android.a)
add_library(pjlib-util STATIC IMPORTED)
set_target_properties(pjlib-util PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjlib-util-aarch64-unknown-linux-android.a)
add_library(pjnath STATIC IMPORTED)
set_target_properties(pjnath PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjnath-aarch64-unknown-linux-android.a)
add_library(pjmedia STATIC IMPORTED)
set_target_properties(pjmedia PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjmedia-aarch64-unknown-linux-android.a)
add_library(pjmedia-audiodev STATIC IMPORTED)
set_target_properties(pjmedia-audiodev PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjmedia-audiodev-aarch64-unknown-linux-android.a)
add_library(pjmedia-codec STATIC IMPORTED)
set_target_properties(pjmedia-codec PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjmedia-codec-aarch64-unknown-linux-android.a)
add_library(pjmedia-videodev STATIC IMPORTED)
set_target_properties(pjmedia-videodev PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjmedia-videodev-aarch64-unknown-linux-android.a)
add_library(pjsdp STATIC IMPORTED)
set_target_properties(pjsdp PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjsdp-aarch64-unknown-linux-android.a)
add_library(pjsip STATIC IMPORTED)
set_target_properties(pjsip PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjsip-aarch64-unknown-linux-android.a)
add_library(pjsip-simple STATIC IMPORTED)
set_target_properties(pjsip-simple PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjsip-simple-aarch64-unknown-linux-android.a)
add_library(pjsip-ua STATIC IMPORTED)
set_target_properties(pjsip-ua PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjsip-ua-aarch64-unknown-linux-android.a)
add_library(pjsua STATIC IMPORTED)
set_target_properties(pjsua PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjsua-aarch64-unknown-linux-android.a)
add_library(pjsua2 STATIC IMPORTED)
set_target_properties(pjsua2 PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libpjsua2-aarch64-unknown-linux-android.a)
add_library(srtp STATIC IMPORTED)
set_target_properties(srtp PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libsrtp-aarch64-unknown-linux-android.a)
add_library(resample STATIC IMPORTED)
set_target_properties(resample PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libresample-aarch64-unknown-linux-android.a)
add_library(webrtc STATIC IMPORTED)
set_target_properties(webrtc PROPERTIES IMPORTED_LOCATION ${PJSIP_LIBS_DIR}/libwebrtc-aarch64-unknown-linux-android.a)
# Linkear todas las bibliotecas en orden correcto
target_link_libraries(gsmgateway
pjsua2
pjsua
pjsip-ua
pjsip-simple
pjsip
pjmedia-codec
pjmedia
pjmedia-audiodev
pjmedia-videodev
pjsdp
pjnath
pjlib-util
pj
srtp
resample
webrtc
mediandk
log
android
OpenSLES
)

View File

@@ -0,0 +1,189 @@
#include <jni.h>
#include <string>
#include <android/log.h>
#include "pjsip_wrapper.h"
#define LOG_TAG "GSMGateway-JNI"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
// ============================================
// TEST INICIAL
// ============================================
extern "C" JNIEXPORT jstring JNICALL
Java_com_gqlabs_gsmgateway_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
LOGI("🚀 GSM Gateway Native Library Loaded");
// Test básico de PJSIP
int status = gateway_init();
std::string result;
if (status == 0) {
LOGI("✅ Gateway initialized successfully");
result = "✅ PJSIP Gateway Ready!\n\n";
result += "Version: 2.14\n";
result += "Status: Initialized\n\n";
result += "Ready to register to PBX";
// Cleanup test
gateway_destroy();
} else {
LOGE("❌ Gateway initialization failed: %d", status);
result = "❌ Gateway initialization failed\n";
result += "Error: ";
result += gateway_get_last_error();
}
return env->NewStringUTF(result.c_str());
}
// ============================================
// FUNCIONES JNI - INICIALIZACIÓN
// ============================================
extern "C" JNIEXPORT jint JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeInit(
JNIEnv* env,
jobject thiz) {
LOGI("📱 nativeInit called");
return gateway_init();
}
extern "C" JNIEXPORT void JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeDestroy(
JNIEnv* env,
jobject thiz) {
LOGI("🔥 nativeDestroy called");
gateway_destroy();
}
// ============================================
// FUNCIONES JNI - REGISTRO
// ============================================
extern "C" JNIEXPORT jint JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeRegister(
JNIEnv* env,
jobject thiz,
jstring server,
jstring username,
jstring password) {
const char* srv = env->GetStringUTFChars(server, nullptr);
const char* user = env->GetStringUTFChars(username, nullptr);
const char* pass = env->GetStringUTFChars(password, nullptr);
LOGI("📞 nativeRegister: %s@%s", user, srv);
int result = gateway_register(srv, user, pass);
env->ReleaseStringUTFChars(server, srv);
env->ReleaseStringUTFChars(username, user);
env->ReleaseStringUTFChars(password, pass);
return result;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeUnregister(
JNIEnv* env,
jobject thiz) {
LOGI("📴 nativeUnregister called");
return gateway_unregister();
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeIsRegistered(
JNIEnv* env,
jobject thiz) {
return gateway_is_registered() ? JNI_TRUE : JNI_FALSE;
}
// ============================================
// FUNCIONES JNI - LLAMADAS
// ============================================
extern "C" JNIEXPORT jint JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeMakeCall(
JNIEnv* env,
jobject thiz,
jstring dest_uri) {
const char* uri = env->GetStringUTFChars(dest_uri, nullptr);
LOGI("📲 nativeMakeCall: %s", uri);
int call_id = gateway_make_call(uri);
env->ReleaseStringUTFChars(dest_uri, uri);
return call_id;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeAnswerCall(
JNIEnv* env,
jobject thiz,
jint call_id) {
LOGI("✅ nativeAnswerCall: %d", call_id);
return gateway_answer_call(call_id);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeHangupCall(
JNIEnv* env,
jobject thiz,
jint call_id) {
LOGI("📴 nativeHangupCall: %d", call_id);
return gateway_hangup_call(call_id);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeRejectCall(
JNIEnv* env,
jobject thiz,
jint call_id) {
LOGI("🚫 nativeRejectCall: %d", call_id);
return gateway_reject_call(call_id);
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeGetCallInfo(
JNIEnv* env,
jobject thiz,
jint call_id) {
char info[256];
int status = gateway_get_call_info(call_id, info, sizeof(info));
if (status == 0) {
return env->NewStringUTF(info);
} else {
return env->NewStringUTF("Call info not available");
}
}
// ============================================
// FUNCIONES JNI - UTILIDADES
// ============================================
extern "C" JNIEXPORT jstring JNICALL
Java_com_gqlabs_gsmgateway_PJSIPManager_nativeGetLastError(
JNIEnv* env,
jobject thiz) {
return env->NewStringUTF(gateway_get_last_error());
}

View File

@@ -0,0 +1,187 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_FILE_HPP__
#define __PJPP_FILE_HPP__
#include <pj/file_io.h>
#include <pj/file_access.h>
#include <pj++/types.hpp>
#include <pj++/pool.hpp>
//
// File API.
//
class Pj_File_API
{
public:
//
// Check file existance.
//
static bool file_exists(const char *filename)
{
return pj_file_exists(filename) != 0;
}
//
// Get file size.
//
static pj_off_t file_size(const char *filename)
{
return pj_file_size(filename);
}
//
// Delete file.
//
static pj_status_t file_delete(const char *filename)
{
return pj_file_delete(filename);
}
//
// Move/rename file.
//
static pj_status_t file_move(const char *oldname, const char *newname)
{
return pj_file_move(oldname, newname);
}
//
// Get stat.
//
static pj_status_t file_stat(const char *filename, pj_file_stat *buf)
{
return pj_file_getstat(filename, buf);
}
};
//
// File.
//
class Pj_File : public Pj_Object
{
public:
//
// Offset type to be used in setpos.
//
enum Offset_Type
{
PJ_SEEK_SET = PJ_SEEK_SET,
PJ_SEEK_CUR = PJ_SEEK_CUR,
PJ_SEEK_END = PJ_SEEK_END,
};
//
// Default constructor.
//
Pj_File()
: hnd_(0)
{
}
//
// Construct and open a file.
//
Pj_File(Pj_Pool *pool, const char *filename,
unsigned access = PJ_O_RDONLY)
: hnd_(NULL)
{
open(pool, filename, access);
}
//
// Destructor closes the file.
//
~Pj_File()
{
close();
}
//
// Open a file.
//
pj_status_t open(Pj_Pool *pool, const char *filename,
unsigned access = PJ_O_RDONLY )
{
close();
return pj_file_open(pool->pool_(), filename, access, &hnd_);
}
//
// Close a file.
//
void close()
{
if (hnd_ != 0) {
pj_file_close(hnd_);
hnd_ = 0;
}
}
//
// Write data.
//
pj_ssize_t write(const void *buff, pj_size_t size)
{
pj_ssize_t bytes = size;
if (pj_file_write(hnd_, buff, &bytes) != PJ_SUCCESS)
return -1;
return bytes;
}
//
// Read data.
//
pj_ssize_t read(void *buf, pj_size_t size)
{
pj_ssize_t bytes = size;
if (pj_file_read(hnd_, buf, &bytes) != PJ_SUCCESS)
return -1;
return bytes;
}
//
// Set file position.
//
pj_status_t setpos(pj_off_t offset, Offset_Type whence)
{
return pj_file_setpos(hnd_, offset,
(enum pj_file_seek_type)whence);
}
//
// Get file position.
//
pj_off_t getpos()
{
pj_off_t pos;
if (pj_file_getpos(hnd_, &pos) != PJ_SUCCESS)
return -1;
return pos;
}
private:
pj_oshandle_t hnd_;
};
#endif /* __PJPP_FILE_HPP__ */

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_HASH_HPP__
#define __PJPP_HASH_HPP__
#include <pj++/types.hpp>
#include <pj++/pool.hpp>
#include <pj/hash.h>
//
// Hash table.
//
class Pj_Hash_Table : public Pj_Object
{
public:
//
// Hash table iterator.
//
class iterator
{
public:
iterator()
{
}
explicit iterator(pj_hash_table_t *h, pj_hash_iterator_t *i)
: ht_(h), it_(i)
{
}
iterator(const iterator &rhs)
: ht_(rhs.ht_), it_(rhs.it_)
{
}
void operator++()
{
it_ = pj_hash_next(ht_, it_);
}
bool operator==(const iterator &rhs)
{
return ht_ == rhs.ht_ && it_ == rhs.it_;
}
iterator & operator=(const iterator &rhs)
{
ht_=rhs.ht_; it_=rhs.it_;
return *this;
}
private:
pj_hash_table_t *ht_;
pj_hash_iterator_t it_val_;
pj_hash_iterator_t *it_;
friend class Pj_Hash_Table;
};
//
// Construct hash table.
//
Pj_Hash_Table(Pj_Pool *pool, unsigned size)
{
table_ = pj_hash_create(pool->pool_(), size);
}
//
// Destroy hash table.
//
~Pj_Hash_Table()
{
}
//
// Calculate hash value.
//
static pj_uint32_t calc( pj_uint32_t initial_hval,
const void *key,
unsigned keylen = PJ_HASH_KEY_STRING)
{
return pj_hash_calc(initial_hval, key, keylen);
}
//
// Return pjlib compatible hash table object.
//
pj_hash_table_t *pj_hash_table_t_()
{
return table_;
}
//
// Get the value associated with the specified key.
//
void *get(const void *key, unsigned keylen = PJ_HASH_KEY_STRING)
{
return pj_hash_get(table_, key, keylen);
}
//
// Associate a value with a key.
// Set the value to NULL to delete the key from the hash table.
//
void set(Pj_Pool *pool,
const void *key,
void *value,
unsigned keylen = PJ_HASH_KEY_STRING)
{
pj_hash_set(pool->pool_(), table_, key, keylen, value);
}
//
// Get number of items in the hash table.
//
unsigned count()
{
return pj_hash_count(table_);
}
//
// Iterate hash table.
//
iterator begin()
{
iterator it(table_, NULL);
it.it_ = pj_hash_first(table_, &it.it_val_);
return it;
}
//
// End of items.
//
iterator end()
{
return iterator(table_, NULL);
}
private:
pj_hash_table_t *table_;
};
#endif /* __PJPP_HASH_HPP__ */

View File

@@ -0,0 +1,351 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_LIST_HPP__
#define __PJPP_LIST_HPP__
#include <pj/list.h>
#include <pj++/pool.hpp>
//
// Linked-list.
//
// Note:
// List_Node must have public member next and prev. Normally
// it will be declared like:
//
// struct my_node
// {
// PJ_DECL_LIST_MEMBER(struct my_node);
// ..
// };
//
//
template <class List_Node>
class Pj_List : public Pj_Object
{
public:
//
// List const_iterator.
//
class const_iterator
{
public:
const_iterator()
: node_(NULL)
{}
const_iterator(const List_Node *nd)
: node_((List_Node*)nd)
{}
const List_Node * operator *()
{
return node_;
}
const List_Node * operator -> ()
{
return node_;
}
const_iterator operator++()
{
return const_iterator((const List_Node *)node_->next);
}
bool operator==(const const_iterator &rhs)
{
return node_ == rhs.node_;
}
bool operator!=(const const_iterator &rhs)
{
return node_ != rhs.node_;
}
protected:
List_Node *node_;
};
//
// List iterator.
//
class iterator : public const_iterator
{
public:
iterator()
{}
iterator(List_Node *nd)
: const_iterator(nd)
{}
List_Node * operator *()
{
return node_;
}
List_Node * operator -> ()
{
return node_;
}
iterator operator++()
{
return iterator((List_Node*)node_->next);
}
bool operator==(const iterator &rhs)
{
return node_ == rhs.node_;
}
bool operator!=(const iterator &rhs)
{
return node_ != rhs.node_;
}
};
//
// Default constructor.
//
Pj_List()
{
pj_list_init(&root_);
if (0) compiletest();
}
//
// You can cast Pj_List to pj_list
//
operator pj_list&()
{
return (pj_list&)root_;
}
operator const pj_list&()
{
return (const pj_list&)root_;
}
//
// You can cast Pj_List to pj_list* too
//
operator pj_list*()
{
return (pj_list*)&root_;
}
operator const pj_list*()
{
return (const pj_list*)&root_;
}
//
// Check if list is empty.
//
bool empty() const
{
return pj_list_empty(&root_);
}
//
// Get first element.
//
iterator begin()
{
return iterator(root_.next);
}
//
// Get first element.
//
const_iterator begin() const
{
return const_iterator(root_.next);
}
//
// Get end-of-element
//
const_iterator end() const
{
return const_iterator((List_Node*)&root_);
}
//
// Get end-of-element
//
iterator end()
{
return iterator((List_Node*)&root_);
}
//
// Insert node.
//
void insert_before (iterator &pos, List_Node *node)
{
pj_list_insert_before( *pos, node );
}
//
// Insert node.
//
void insert_after(iterator &pos, List_Node *node)
{
pj_list_insert_after(*pos, node);
}
//
// Merge list.
//
void merge_first(List_Node *list2)
{
pj_list_merge_first(&root_, list2);
}
//
// Merge list.
//
void merge_last(Pj_List *list)
{
pj_list_merge_last(&root_, &list->root_);
}
//
// Insert list.
//
void insert_nodes_before(iterator &pos, Pj_List *list2)
{
pj_list_insert_nodes_before(*pos, &list2->root_);
}
//
// Insert list.
//
void insert_nodes_after(iterator &pos, Pj_List *list2)
{
pj_list_insert_nodes_after(*pos, &list2->root_);
}
//
// Erase an element.
//
void erase(iterator &it)
{
pj_list_erase(*it);
}
//
// Get first element.
//
List_Node *front()
{
return root_.next;
}
//
// Get first element.
//
const List_Node *front() const
{
return root_.next;
}
//
// Remove first element.
//
void pop_front()
{
pj_list_erase(root_.next);
}
//
// Get last element.
//
List_Node *back()
{
return root_.prev;
}
//
// Get last element.
//
const List_Node *back() const
{
return root_.prev;
}
//
// Remove last element.
//
void pop_back()
{
pj_list_erase(root_.prev);
}
//
// Find a node.
//
iterator find(List_Node *node)
{
List_Node *n = pj_list_find_node(&root_, node);
return n ? iterator(n) : end();
}
//
// Find a node.
//
const_iterator find(List_Node *node) const
{
List_Node *n = pj_list_find_node(&root_, node);
return n ? const_iterator(n) : end();
}
//
// Insert a node in the back.
//
void push_back(List_Node *node)
{
pj_list_insert_after(root_.prev, node);
}
//
// Insert a node in the front.
//
void push_front(List_Node *node)
{
pj_list_insert_before(root_.next, node);
}
//
// Remove all elements.
//
void clear()
{
root_.next = &root_;
root_.prev = &root_;
}
private:
struct RootNode
{
PJ_DECL_LIST_MEMBER(List_Node);
} root_;
void compiletest()
{
// If you see error in this line,
// it's because List_Node is not derived from Pj_List_Node.
List_Node *n = (List_Node*)0;
n = (List_Node *)n->next; n = (List_Node *)n->prev;
}
};
#endif /* __PJPP_LIST_HPP__ */

View File

@@ -0,0 +1,148 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_LOCK_HPP__
#define __PJPP_LOCK_HPP__
#include <pj++/types.hpp>
#include <pj/lock.h>
#include <pj++/pool.hpp>
//////////////////////////////////////////////////////////////////////////////
// Lock object.
//
class Pj_Lock : public Pj_Object
{
public:
//
// Constructor.
//
explicit Pj_Lock(pj_lock_t *lock)
: lock_(lock)
{
}
//
// Destructor.
//
~Pj_Lock()
{
if (lock_)
pj_lock_destroy(lock_);
}
//
// Get pjlib compatible lock object.
//
pj_lock_t *pj_lock_t_()
{
return lock_;
}
//
// acquire lock.
//
pj_status_t acquire()
{
return pj_lock_acquire(lock_);
}
//
// release lock,.
//
pj_status_t release()
{
return pj_lock_release(lock_);
}
protected:
pj_lock_t *lock_;
};
//////////////////////////////////////////////////////////////////////////////
// Null lock object.
//
class Pj_Null_Lock : public Pj_Lock
{
public:
//
// Default constructor.
//
explicit Pj_Null_Lock(Pj_Pool *pool, const char *name = NULL)
: Pj_Lock(NULL)
{
pj_lock_create_null_mutex(pool->pool_(), name, &lock_);
}
};
//////////////////////////////////////////////////////////////////////////////
// Simple mutex lock object.
//
class Pj_Simple_Mutex_Lock : public Pj_Lock
{
public:
//
// Default constructor.
//
explicit Pj_Simple_Mutex_Lock(Pj_Pool *pool, const char *name = NULL)
: Pj_Lock(NULL)
{
pj_lock_create_simple_mutex(pool->pool_(), name, &lock_);
}
};
//////////////////////////////////////////////////////////////////////////////
// Recursive mutex lock object.
//
class Pj_Recursive_Mutex_Lock : public Pj_Lock
{
public:
//
// Default constructor.
//
explicit Pj_Recursive_Mutex_Lock(Pj_Pool *pool, const char *name = NULL)
: Pj_Lock(NULL)
{
pj_lock_create_recursive_mutex(pool->pool_(), name, &lock_);
}
};
//////////////////////////////////////////////////////////////////////////////
// Semaphore lock object.
//
class Pj_Semaphore_Lock : public Pj_Lock
{
public:
//
// Default constructor.
//
explicit Pj_Semaphore_Lock(Pj_Pool *pool,
unsigned max=PJ_MAXINT32,
unsigned initial=0,
const char *name=NULL)
: Pj_Lock(NULL)
{
pj_lock_create_semaphore(pool->pool_(), name, initial, max, &lock_);
}
};
#endif /* __PJPP_LOCK_HPP__ */

View File

@@ -0,0 +1,869 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_OS_HPP__
#define __PJPP_OS_HPP__
#include <pj/os.h>
#include <pj/string.h>
#include <pj++/types.hpp>
#include <pj++/pool.hpp>
class Pj_Thread;
//
// Thread API.
//
class Pj_Thread_API
{
public:
//
// Create a thread.
//
static pj_status_t create( Pj_Pool *pool, pj_thread_t **thread,
pj_thread_proc *proc, void *arg,
unsigned flags = 0,
const char *name = NULL,
pj_size_t stack_size = 0 )
{
return pj_thread_create(pool->pool_(), name, proc, arg, stack_size,
flags, thread);
}
//
// Register a thread.
//
static pj_status_t register_this_thread( pj_thread_desc desc,
pj_thread_t **thread,
const char *name = NULL )
{
return pj_thread_register( name, desc, thread );
}
//
// Get current thread.
// Will return pj_thread_t (sorry folks, not Pj_Thread).
//
static pj_thread_t *this_thread()
{
return pj_thread_this();
}
//
// Get thread name.
//
static const char *get_name(pj_thread_t *thread)
{
return pj_thread_get_name(thread);
}
//
// Resume thread.
//
static pj_status_t resume(pj_thread_t *thread)
{
return pj_thread_resume(thread);
}
//
// Sleep.
//
static pj_status_t sleep(unsigned msec)
{
return pj_thread_sleep(msec);
}
//
// Join the specified thread.
//
static pj_status_t join(pj_thread_t *thread)
{
return pj_thread_join(thread);
}
//
// Destroy thread
//
static pj_status_t destroy(pj_thread_t *thread)
{
return pj_thread_destroy(thread);
}
};
//
// Thread object.
//
// How to use:
// Derive a class from this class, then override main().
//
class Pj_Thread : public Pj_Object
{
public:
enum Flags
{
FLAG_SUSPENDED = PJ_THREAD_SUSPENDED
};
//
// Default constructor.
//
Pj_Thread()
: thread_(NULL)
{
}
//
// Destroy thread.
//
~Pj_Thread()
{
destroy();
}
//
// This is the main thread function.
//
virtual int main() = 0;
//
// Start a thread.
//
pj_status_t create( Pj_Pool *pool,
unsigned flags = 0,
const char *thread_name = NULL,
pj_size_t stack_size = PJ_THREAD_DEFAULT_STACK_SIZE)
{
destroy();
return Pj_Thread_API::create( pool, &thread_, &thread_proc, this,
flags, thread_name, stack_size);
}
//
// Get pjlib compatible thread object.
//
pj_thread_t *pj_thread_t_()
{
return thread_;
}
//
// Get thread name.
//
const char *get_name()
{
return Pj_Thread_API::get_name(thread_);
}
//
// Resume a suspended thread.
//
pj_status_t resume()
{
return Pj_Thread_API::resume(thread_);
}
//
// Join this thread.
//
pj_status_t join()
{
return Pj_Thread_API::join(thread_);
}
//
// Destroy thread.
//
pj_status_t destroy()
{
if (thread_) {
Pj_Thread_API::destroy(thread_);
thread_ = NULL;
}
}
protected:
pj_thread_t *thread_;
static int PJ_THREAD_FUNC thread_proc(void *obj)
{
Pj_Thread *thread_class = (Pj_Thread*)obj;
return thread_class->main();
}
};
//
// External Thread
// (threads that were started by external means, i.e. not
// with Pj_Thread::create).
//
// This class will normally be defined as local variable in
// external thread's stack, normally inside thread's main proc.
// But be aware that the handle will be destroyed on destructor!
//
class Pj_External_Thread : public Pj_Thread
{
public:
Pj_External_Thread()
{
}
//
// Register external thread so that pjlib functions can work
// in that thread.
//
pj_status_t register_this_thread( const char *name=NULL )
{
return Pj_Thread_API::register_this_thread(desc_, &thread_,name);
}
private:
pj_thread_desc desc_;
};
//
// Thread specific data/thread local storage/TLS.
//
class Pj_Thread_Local_API
{
public:
//
// Allocate thread local storage (TLS) index.
//
static pj_status_t alloc(long *index)
{
return pj_thread_local_alloc(index);
}
//
// Free TLS index.
//
static void free(long index)
{
pj_thread_local_free(index);
}
//
// Set thread specific data.
//
static pj_status_t set(long index, void *value)
{
return pj_thread_local_set(index, value);
}
//
// Get thread specific data.
//
static void *get(long index)
{
return pj_thread_local_get(index);
}
};
//
// Atomic variable
//
// How to use:
// Pj_Atomic_Var var(pool, 0);
// var.set(..);
//
class Pj_Atomic_Var : public Pj_Object
{
public:
//
// Default constructor, initialize variable with NULL.
//
Pj_Atomic_Var()
: var_(NULL)
{
}
//
// Construct atomic variable.
//
Pj_Atomic_Var(Pj_Pool *pool, pj_atomic_value_t value)
: var_(NULL)
{
create(pool, value);
}
//
// Destructor.
//
~Pj_Atomic_Var()
{
destroy();
}
//
// Create atomic variable.
//
pj_status_t create( Pj_Pool *pool, pj_atomic_value_t value)
{
destroy();
return pj_atomic_create(pool->pool_(), value, &var_);
}
//
// Destroy.
//
void destroy()
{
if (var_) {
pj_atomic_destroy(var_);
var_ = NULL;
}
}
//
// Get pjlib compatible atomic variable.
//
pj_atomic_t *pj_atomic_t_()
{
return var_;
}
//
// Set the value.
//
void set(pj_atomic_value_t val)
{
pj_atomic_set(var_, val);
}
//
// Get the value.
//
pj_atomic_value_t get()
{
return pj_atomic_get(var_);
}
//
// Increment.
//
void inc()
{
pj_atomic_inc(var_);
}
//
// Increment and get the result.
//
pj_atomic_value_t inc_and_get()
{
return pj_atomic_inc_and_get(var_);
}
//
// Decrement.
//
void dec()
{
pj_atomic_dec(var_);
}
//
// Decrement and get the result.
//
pj_atomic_value_t dec_and_get()
{
return pj_atomic_dec_and_get(var_);
}
//
// Add the variable.
//
void add(pj_atomic_value_t value)
{
pj_atomic_add(var_, value);
}
//
// Add the variable and get the value.
//
pj_atomic_value_t add_and_get(pj_atomic_value_t value)
{
return pj_atomic_add_and_get(var_, value );
}
private:
pj_atomic_t *var_;
};
//
// Mutex
//
class Pj_Mutex : public Pj_Object
{
public:
//
// Mutex type.
//
enum Type
{
DEFAULT = PJ_MUTEX_DEFAULT,
SIMPLE = PJ_MUTEX_SIMPLE,
RECURSE = PJ_MUTEX_RECURSE,
};
//
// Default constructor will create default mutex.
//
explicit Pj_Mutex(Pj_Pool *pool, Type type = DEFAULT,
const char *name = NULL)
: mutex_(NULL)
{
create(pool, type, name);
}
//
// Destructor.
//
~Pj_Mutex()
{
destroy();
}
//
// Create mutex.
//
pj_status_t create( Pj_Pool *pool, Type type, const char *name = NULL)
{
destroy();
return pj_mutex_create( pool->pool_(), name, type,
&mutex_ );
}
//
// Create simple mutex.
//
pj_status_t create_simple( Pj_Pool *pool,const char *name = NULL)
{
return create(pool, SIMPLE, name);
}
//
// Create recursive mutex.
//
pj_status_t create_recursive( Pj_Pool *pool, const char *name = NULL )
{
return create(pool, RECURSE, name);
}
//
// Get pjlib compatible mutex object.
//
pj_mutex_t *pj_mutex_t_()
{
return mutex_;
}
//
// Destroy mutex.
//
void destroy()
{
if (mutex_) {
pj_mutex_destroy(mutex_);
mutex_ = NULL;
}
}
//
// Lock mutex.
//
pj_status_t acquire()
{
return pj_mutex_lock(mutex_);
}
//
// Unlock mutex.
//
pj_status_t release()
{
return pj_mutex_unlock(mutex_);
}
//
// Try locking the mutex.
//
pj_status_t tryacquire()
{
return pj_mutex_trylock(mutex_);
}
private:
pj_mutex_t *mutex_;
};
//
// Semaphore
//
class Pj_Semaphore : public Pj_Object
{
public:
//
// Construct semaphore
//
Pj_Semaphore(Pj_Pool *pool, unsigned max,
unsigned initial = 0, const char *name = NULL)
: sem_(NULL)
{
create(pool, max, initial, name);
}
//
// Destructor.
//
~Pj_Semaphore()
{
destroy();
}
//
// Create semaphore
//
pj_status_t create( Pj_Pool *pool, unsigned max,
unsigned initial = 0, const char *name = NULL )
{
destroy();
return pj_sem_create( pool->pool_(), name, initial, max, &sem_);
}
//
// Destroy semaphore.
//
void destroy()
{
if (sem_) {
pj_sem_destroy(sem_);
sem_ = NULL;
}
}
//
// Get pjlib compatible semaphore object.
//
pj_sem_t *pj_sem_t_()
{
return (pj_sem_t*)this;
}
//
// Wait semaphore.
//
pj_status_t wait()
{
return pj_sem_wait(this->pj_sem_t_());
}
//
// Wait semaphore.
//
pj_status_t acquire()
{
return wait();
}
//
// Try wait semaphore.
//
pj_status_t trywait()
{
return pj_sem_trywait(this->pj_sem_t_());
}
//
// Try wait semaphore.
//
pj_status_t tryacquire()
{
return trywait();
}
//
// Post semaphore.
//
pj_status_t post()
{
return pj_sem_post(this->pj_sem_t_());
}
//
// Post semaphore.
//
pj_status_t release()
{
return post();
}
private:
pj_sem_t *sem_;
};
//
// Event object.
//
class Pj_Event
{
public:
//
// Construct event object.
//
Pj_Event( Pj_Pool *pool, bool manual_reset = false,
bool initial = false, const char *name = NULL )
: event_(NULL)
{
create(pool, manual_reset, initial, name);
}
//
// Destructor.
//
~Pj_Event()
{
destroy();
}
//
// Create event object.
//
pj_status_t create( Pj_Pool *pool, bool manual_reset = false,
bool initial = false, const char *name = NULL)
{
destroy();
return pj_event_create(pool->pool_(), name, manual_reset, initial,
&event_);
}
//
// Get pjlib compatible event object.
//
pj_event_t *pj_event_t_()
{
return event_;
}
//
// Destroy event object.
//
void destroy()
{
if (event_) {
pj_event_destroy(event_);
event_ = NULL;
}
}
//
// Wait.
//
pj_status_t wait()
{
return pj_event_wait(event_);
}
//
// Try wait.
//
pj_status_t trywait()
{
return pj_event_trywait(event_);
}
//
// Set event state to signalled.
//
pj_status_t set()
{
return pj_event_set(this->pj_event_t_());
}
//
// Release one waiting thread.
//
pj_status_t pulse()
{
return pj_event_pulse(this->pj_event_t_());
}
//
// Set a non-signalled.
//
pj_status_t reset()
{
return pj_event_reset(this->pj_event_t_());
}
private:
pj_event_t *event_;
};
//
// Timestamp
//
class Pj_Timestamp
{
public:
pj_status_t get_timestamp()
{
return pj_get_timestamp(&ts_);
}
Pj_Timestamp& operator += (const Pj_Timestamp &rhs)
{
pj_add_timestamp(&ts_, &rhs.ts_);
return *this;
}
Pj_Timestamp& operator -= (const Pj_Timestamp &rhs)
{
pj_sub_timestamp(&ts_, &rhs.ts_);
return *this;
}
Pj_Time_Val to_time() const
{
Pj_Timestamp zero;
pj_memset(&zero, 0, sizeof(zero));
return Pj_Time_Val(pj_elapsed_time(&zero.ts_, &ts_));
}
pj_uint32_t to_msec() const
{
Pj_Timestamp zero;
pj_memset(&zero, 0, sizeof(zero));
return pj_elapsed_msec(&zero.ts_, &ts_);
}
pj_uint32_t to_usec() const
{
Pj_Timestamp zero;
pj_memset(&zero, 0, sizeof(zero));
return pj_elapsed_usec(&zero.ts_, &ts_);
}
pj_uint32_t to_nanosec() const
{
Pj_Timestamp zero;
pj_memset(&zero, 0, sizeof(zero));
return pj_elapsed_nanosec(&zero.ts_, &ts_);
}
pj_uint32_t to_cycle() const
{
Pj_Timestamp zero;
pj_memset(&zero, 0, sizeof(zero));
return pj_elapsed_cycle(&zero.ts_, &ts_);
}
private:
pj_timestamp ts_;
};
//
// OS abstraction.
//
class Pj_OS_API
{
public:
//
// Get current time.
//
static pj_status_t gettimeofday( Pj_Time_Val *tv )
{
return pj_gettimeofday(tv);
}
//
// Parse to time of day.
//
static pj_status_t time_decode( const Pj_Time_Val *tv,
pj_parsed_time *pt )
{
return pj_time_decode(tv, pt);
}
//
// Parse from time of day.
//
static pj_status_t time_encode( const pj_parsed_time *pt,
Pj_Time_Val *tv)
{
return pj_time_encode(pt, tv);
}
//
// Convert to GMT.
//
static pj_status_t time_local_to_gmt( Pj_Time_Val *tv )
{
return pj_time_local_to_gmt( tv );
}
//
// Convert time to local.
//
static pj_status_t time_gmt_to_local( Pj_Time_Val *tv)
{
return pj_time_gmt_to_local( tv );
}
};
//
// Timeval inlines.
//
inline pj_status_t Pj_Time_Val::gettimeofday()
{
return Pj_OS_API::gettimeofday(this);
}
inline pj_parsed_time Pj_Time_Val::decode()
{
pj_parsed_time pt;
Pj_OS_API::time_decode(this, &pt);
return pt;
}
inline pj_status_t Pj_Time_Val::encode(const pj_parsed_time *pt)
{
return Pj_OS_API::time_encode(pt, this);
}
inline pj_status_t Pj_Time_Val::to_gmt()
{
return Pj_OS_API::time_local_to_gmt(this);
}
inline pj_status_t Pj_Time_Val::to_local()
{
return Pj_OS_API::time_gmt_to_local(this);
}
#endif /* __PJPP_OS_HPP__ */

View File

@@ -0,0 +1,278 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_POOL_HPP__
#define __PJPP_POOL_HPP__
#include <pj/pool.h>
class Pj_Pool;
class Pj_Caching_Pool;
//
// Base class for all Pjlib objects
//
class Pj_Object
{
public:
void *operator new(unsigned int class_size, Pj_Pool *pool);
void *operator new(unsigned int class_size, Pj_Pool &pool);
void operator delete(void*)
{
}
void operator delete(void*, Pj_Pool*)
{
}
void operator delete(void*, Pj_Pool&)
{
}
//
// Inline implementations at the end of this file.
//
private:
// Can not use normal new operator; must use pool.
// e.g.:
// obj = new(pool) Pj_The_Object(pool, ...);
//
void *operator new(unsigned int)
{}
};
//
// Pool.
//
class Pj_Pool : public Pj_Object
{
public:
//
// Default constructor, initializes internal pool to NULL.
// Application must call attach() some time later.
//
Pj_Pool()
: p_(NULL)
{
}
//
// Create pool.
//
Pj_Pool(Pj_Caching_Pool &caching_pool,
pj_size_t initial_size,
pj_size_t increment_size,
const char *name = NULL,
pj_pool_callback *callback = NULL);
//
// Construct from existing pool.
//
explicit Pj_Pool(pj_pool_t *pool)
: p_(pool)
{
}
//
// Attach existing pool.
//
void attach(pj_pool_t *pool)
{
p_ = pool;
}
//
// Destructor.
//
// Release pool back to factory. Remember: if you delete pool, then
// make sure that all objects that have been allocated from this pool
// have been properly destroyed.
//
// This is where C++ is trickier than plain C!!
//
~Pj_Pool()
{
if (p_)
pj_pool_release(p_);
}
//
// Get name.
//
const char *getobjname() const
{
return pj_pool_getobjname(p_);
}
//
// You can cast Pj_Pool to pj_pool_t*
//
operator pj_pool_t*()
{
return p_;
}
//
// Get pjlib compatible pool object.
//
pj_pool_t *pool_()
{
return p_;
}
//
// Get pjlib compatible pool object.
//
const pj_pool_t *pool_() const
{
return p_;
}
//
// Get pjlib compatible pool object.
//
pj_pool_t *pj_pool_t_()
{
return p_;
}
//
// Reset pool.
//
void reset()
{
pj_pool_reset(p_);
}
//
// Get current capacity.
//
pj_size_t get_capacity()
{
pj_pool_get_capacity(p_);
}
//
// Get current total bytes allocated from the pool.
//
pj_size_t get_used_size()
{
pj_pool_get_used_size(p_);
}
//
// Allocate.
//
void *alloc(pj_size_t size)
{
return pj_pool_alloc(p_, size);
}
//
// Allocate elements and zero fill the memory.
//
void *calloc(pj_size_t count, pj_size_t elem)
{
return pj_pool_calloc(p_, count, elem);
}
//
// Allocate and zero fill memory.
//
void *zalloc(pj_size_t size)
{
return pj_pool_zalloc(p_, size);
}
private:
pj_pool_t *p_;
};
//
// Caching pool.
//
class Pj_Caching_Pool
{
public:
//
// Construct caching pool.
//
Pj_Caching_Pool( pj_size_t cache_capacity = 0,
const pj_pool_factory_policy *pol=&pj_pool_factory_default_policy)
{
pj_caching_pool_init(&cp_, pol, cache_capacity);
}
//
// Destroy caching pool.
//
~Pj_Caching_Pool()
{
pj_caching_pool_destroy(&cp_);
}
//
// Create pool.
//
pj_pool_t *create_pool( pj_size_t initial_size,
pj_size_t increment_size,
const char *name = NULL,
pj_pool_callback *callback = NULL)
{
return (pj_pool_t*)(*cp_.factory.create_pool)(&cp_.factory, name,
initial_size,
increment_size,
callback);
}
private:
pj_caching_pool cp_;
};
//
// Inlines for Pj_Object
//
inline void *Pj_Object::operator new(unsigned int class_size, Pj_Pool *pool)
{
return pool->alloc(class_size);
}
inline void *Pj_Object::operator new(unsigned int class_size, Pj_Pool &pool)
{
return pool.alloc(class_size);
}
//
// Inlines for Pj_Pool
//
inline Pj_Pool::Pj_Pool( Pj_Caching_Pool &caching_pool,
pj_size_t initial_size,
pj_size_t increment_size,
const char *name,
pj_pool_callback *callback)
{
p_ = caching_pool.create_pool(initial_size, increment_size, name,
callback);
}
#endif /* __PJPP_POOL_HPP__ */

View File

@@ -0,0 +1,514 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_PROACTOR_HPP__
#define __PJPP_PROACTOR_HPP__
#include <pj/ioqueue.h>
#include <pj++/pool.hpp>
#include <pj++/sock.hpp>
#include <pj++/timer.hpp>
#include <pj/errno.h>
class Pj_Proactor;
class Pj_Event_Handler;
//////////////////////////////////////////////////////////////////////////////
// Asynchronous operation key.
//
// Applications may inheric this class to put their application
// specific data.
//
class Pj_Async_Op : public pj_ioqueue_op_key_t
{
public:
//
// Construct with null handler.
// App must call set_handler() before use.
//
Pj_Async_Op()
: handler_(NULL)
{
pj_ioqueue_op_key_init(this, sizeof(*this));
}
//
// Constructor.
//
explicit Pj_Async_Op(Pj_Event_Handler *handler)
: handler_(handler)
{
pj_ioqueue_op_key_init(this, sizeof(*this));
}
//
// Set handler.
//
void set_handler(Pj_Event_Handler *handler)
{
handler_ = handler;
}
//
// Check whether operation is still pending for this key.
//
bool is_pending();
//
// Cancel the operation.
//
bool cancel(pj_ssize_t bytes_status=-PJ_ECANCELLED);
protected:
Pj_Event_Handler *handler_;
};
//////////////////////////////////////////////////////////////////////////////
// Event handler.
//
// Applications should inherit this class to receive various event
// notifications.
//
// Applications should implement get_socket_handle().
//
class Pj_Event_Handler : public Pj_Object
{
friend class Pj_Proactor;
public:
//
// Default constructor.
//
Pj_Event_Handler()
: key_(NULL)
{
pj_memset(&timer_, 0, sizeof(timer_));
timer_.user_data = this;
timer_.cb = &timer_callback;
}
//
// Destroy.
//
virtual ~Pj_Event_Handler()
{
unregister();
}
//
// Unregister this handler from the ioqueue.
//
void unregister()
{
if (key_) {
pj_ioqueue_unregister(key_);
key_ = NULL;
}
}
//
// Get socket handle associated with this.
//
virtual pj_sock_t get_socket_handle()
{
return PJ_INVALID_SOCKET;
}
//
// Start async receive.
//
pj_status_t recv( Pj_Async_Op *op_key,
void *buf, pj_ssize_t *len,
unsigned flags)
{
return pj_ioqueue_recv( key_, op_key,
buf, len, flags);
}
//
// Start async recvfrom()
//
pj_status_t recvfrom( Pj_Async_Op *op_key,
void *buf, pj_ssize_t *len, unsigned flags,
Pj_Inet_Addr *addr)
{
addr->addrlen_ = sizeof(Pj_Inet_Addr);
return pj_ioqueue_recvfrom( key_, op_key, buf, len, flags,
addr, &addr->addrlen_ );
}
//
// Start async send()
//
pj_status_t send( Pj_Async_Op *op_key,
const void *data, pj_ssize_t *len,
unsigned flags)
{
return pj_ioqueue_send( key_, op_key, data, len, flags);
}
//
// Start async sendto()
//
pj_status_t sendto( Pj_Async_Op *op_key,
const void *data, pj_ssize_t *len, unsigned flags,
const Pj_Inet_Addr &addr)
{
return pj_ioqueue_sendto(key_, op_key, data, len, flags,
&addr, sizeof(addr));
}
#if PJ_HAS_TCP
//
// Start async connect()
//
pj_status_t connect(const Pj_Inet_Addr &addr)
{
return pj_ioqueue_connect(key_, &addr, sizeof(addr));
}
//
// Start async accept().
//
pj_status_t accept( Pj_Async_Op *op_key,
Pj_Socket *sock,
Pj_Inet_Addr *local = NULL,
Pj_Inet_Addr *remote = NULL)
{
int *addrlen = local ? &local->addrlen_ : NULL;
return pj_ioqueue_accept( key_, op_key, &sock->sock_,
local, remote, addrlen );
}
#endif
protected:
//////////////////
// Overridables
//////////////////
//
// Timeout callback.
//
virtual void on_timeout(int)
{
}
//
// On read complete callback.
//
virtual void on_read_complete( Pj_Async_Op*, pj_ssize_t)
{
}
//
// On write complete callback.
//
virtual void on_write_complete( Pj_Async_Op *, pj_ssize_t)
{
}
#if PJ_HAS_TCP
//
// On connect complete callback.
//
virtual void on_connect_complete(pj_status_t)
{
}
//
// On new connection callback.
//
virtual void on_accept_complete( Pj_Async_Op*, pj_sock_t, pj_status_t)
{
}
#endif
private:
pj_ioqueue_key_t *key_;
pj_timer_entry timer_;
friend class Pj_Proactor;
friend class Pj_Async_Op;
//
// Static timer callback.
//
static void timer_callback( pj_timer_heap_t*,
struct pj_timer_entry *entry)
{
Pj_Event_Handler *handler =
(Pj_Event_Handler*) entry->user_data;
handler->on_timeout(entry->id);
}
};
inline bool Pj_Async_Op::is_pending()
{
return pj_ioqueue_is_pending(handler_->key_, this) != 0;
}
inline bool Pj_Async_Op::cancel(pj_ssize_t bytes_status)
{
return pj_ioqueue_post_completion(handler_->key_, this,
bytes_status) == PJ_SUCCESS;
}
//////////////////////////////////////////////////////////////////////////////
// Proactor
//
class Pj_Proactor : public Pj_Object
{
public:
//
// Default constructor, initializes to NULL.
//
Pj_Proactor()
: ioq_(NULL), th_(NULL)
{
cb_.on_read_complete = &read_complete_cb;
cb_.on_write_complete = &write_complete_cb;
cb_.on_accept_complete = &accept_complete_cb;
cb_.on_connect_complete = &connect_complete_cb;
}
//
// Construct proactor.
//
Pj_Proactor( Pj_Pool *pool, pj_size_t max_fd,
pj_size_t max_timer_entries )
: ioq_(NULL), th_(NULL)
{
cb_.on_read_complete = &read_complete_cb;
cb_.on_write_complete = &write_complete_cb;
cb_.on_accept_complete = &accept_complete_cb;
cb_.on_connect_complete = &connect_complete_cb;
create(pool, max_fd, max_timer_entries);
}
//
// Destructor.
//
~Pj_Proactor()
{
destroy();
}
//
// Create proactor.
//
pj_status_t create( Pj_Pool *pool, pj_size_t max_fd,
pj_size_t timer_entry_count)
{
pj_status_t status;
destroy();
status = pj_ioqueue_create(pool->pool_(), max_fd, &ioq_);
if (status != PJ_SUCCESS)
return status;
status = pj_timer_heap_create(pool->pool_(),
timer_entry_count, &th_);
if (status != PJ_SUCCESS) {
pj_ioqueue_destroy(ioq_);
ioq_ = NULL;
return NULL;
}
return status;
}
//
// Destroy proactor.
//
void destroy()
{
if (ioq_) {
pj_ioqueue_destroy(ioq_);
ioq_ = NULL;
}
if (th_) {
pj_timer_heap_destroy(th_);
th_ = NULL;
}
}
//
// Register handler.
// This will call handler->get_socket_handle()
//
pj_status_t register_socket_handler(Pj_Pool *pool,
Pj_Event_Handler *handler)
{
return pj_ioqueue_register_sock( pool->pool_(), ioq_,
handler->get_socket_handle(),
handler, &cb_, &handler->key_ );
}
//
// Unregister handler.
//
static void unregister_handler(Pj_Event_Handler *handler)
{
if (handler->key_) {
pj_ioqueue_unregister( handler->key_ );
handler->key_ = NULL;
}
}
//
// Scheduler timer.
//
bool schedule_timer( Pj_Event_Handler *handler,
const Pj_Time_Val &delay,
int id=-1)
{
return schedule_timer(th_, handler, delay, id);
}
//
// Cancel timer.
//
bool cancel_timer(Pj_Event_Handler *handler)
{
return pj_timer_heap_cancel(th_, &handler->timer_) == 1;
}
//
// Handle events.
//
int handle_events(Pj_Time_Val *max_timeout)
{
Pj_Time_Val timeout(0, 0);
int timer_count;
timer_count = pj_timer_heap_poll( th_, &timeout );
if (timeout.get_sec() < 0)
timeout.sec = PJ_MAXINT32;
/* If caller specifies maximum time to wait, then compare the value
* with the timeout to wait from timer, and use the minimum value.
*/
if (max_timeout && timeout >= *max_timeout) {
timeout = *max_timeout;
}
/* Poll events in ioqueue. */
int ioqueue_count;
ioqueue_count = pj_ioqueue_poll(ioq_, &timeout);
if (ioqueue_count < 0)
return ioqueue_count;
return ioqueue_count + timer_count;
}
//
// Get the internal ioqueue object.
//
pj_ioqueue_t *get_io_queue()
{
return ioq_;
}
//
// Get the internal timer heap object.
//
pj_timer_heap_t *get_timer_heap()
{
return th_;
}
private:
pj_ioqueue_t *ioq_;
pj_timer_heap_t *th_;
pj_ioqueue_callback cb_;
static bool schedule_timer( pj_timer_heap_t *timer,
Pj_Event_Handler *handler,
const Pj_Time_Val &delay,
int id=-1)
{
handler->timer_.id = id;
return pj_timer_heap_schedule(timer, &handler->timer_, &delay) == 0;
}
//
// Static read completion callback.
//
static void read_complete_cb( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_ssize_t bytes_read)
{
Pj_Event_Handler *handler =
(Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
handler->on_read_complete((Pj_Async_Op*)op_key, bytes_read);
}
//
// Static write completion callback.
//
static void write_complete_cb(pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_ssize_t bytes_sent)
{
Pj_Event_Handler *handler =
(Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
handler->on_write_complete((Pj_Async_Op*)op_key, bytes_sent);
}
//
// Static accept completion callback.
//
static void accept_complete_cb(pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_sock_t new_sock,
pj_status_t status)
{
Pj_Event_Handler *handler =
(Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
handler->on_accept_complete((Pj_Async_Op*)op_key, new_sock, status);
}
//
// Static connect completion callback.
//
static void connect_complete_cb(pj_ioqueue_key_t *key,
pj_status_t status)
{
Pj_Event_Handler *handler =
(Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
handler->on_connect_complete(status);
}
};
#endif /* __PJPP_PROACTOR_HPP__ */

View File

@@ -0,0 +1,245 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_SCANNER_HPP__
#define __PJPP_SCANNER_HPP__
#include <pjlib-util/scanner.h>
#include <pj++/string.hpp>
class Pj_Cis;
class Pj_Cis_Buffer;
class Pj_Scanner;
class Pj_Cis_Buffer
{
friend class Pj_Cis;
public:
Pj_Cis_Buffer()
{
pj_cis_buf_init(&buf_);
}
private:
pj_cis_buf_t buf_;
};
class Pj_Cis
{
friend class Pj_Scanner;
public:
Pj_Cis(Pj_Cis_Buffer *buf)
{
pj_cis_init(&buf->buf_, &cis_);
}
Pj_Cis(const Pj_Cis &rhs)
{
pj_cis_dup(&cis_, (pj_cis_t*)&rhs.cis_);
}
void add_range(int start, int end)
{
pj_cis_add_range(&cis_, start, end);
}
void add_alpha()
{
pj_cis_add_alpha(&cis_);
}
void add_num()
{
pj_cis_add_num(&cis_);
}
void add_str(const char *str)
{
pj_cis_add_str(&cis_, str);
}
void add_cis(const Pj_Cis &rhs)
{
pj_cis_add_cis(&cis_, &rhs.cis_);
}
void del_range(int start, int end)
{
pj_cis_del_range(&cis_, start, end);
}
void del_str(const char *str)
{
pj_cis_del_str(&cis_, str);
}
void invert()
{
pj_cis_invert(&cis_);
}
bool match(int c) const
{
return pj_cis_match(&cis_, c) != 0;
}
private:
pj_cis_t cis_;
};
class Pj_Scanner
{
public:
Pj_Scanner() {}
enum
{
SYNTAX_ERROR = 101
};
static void syntax_error_handler_throw_pj(pj_scanner *);
typedef pj_scan_state State;
void init(char *buf, int len, unsigned options=PJ_SCAN_AUTOSKIP_WS,
pj_syn_err_func_ptr callback = &syntax_error_handler_throw_pj)
{
pj_scan_init(&scanner_, buf, len, options, callback);
}
void fini()
{
pj_scan_fini(&scanner_);
}
int eof() const
{
return pj_scan_is_eof(&scanner_);
}
int peek_char() const
{
return *scanner_.curptr;
}
int peek(const Pj_Cis *cis, Pj_String *out)
{
return pj_scan_peek(&scanner_, &cis->cis_, out);
}
int peek_n(pj_size_t len, Pj_String *out)
{
return pj_scan_peek_n(&scanner_, len, out);
}
int peek_until(const Pj_Cis *cis, Pj_String *out)
{
return pj_scan_peek_until(&scanner_, &cis->cis_, out);
}
void get(const Pj_Cis *cis, Pj_String *out)
{
pj_scan_get(&scanner_, &cis->cis_, out);
}
void get_n(unsigned N, Pj_String *out)
{
pj_scan_get_n(&scanner_, N, out);
}
int get_char()
{
return pj_scan_get_char(&scanner_);
}
void get_quote(int begin_quote, int end_quote, Pj_String *out)
{
pj_scan_get_quote(&scanner_, begin_quote, end_quote, out);
}
void get_newline()
{
pj_scan_get_newline(&scanner_);
}
void get_until(const Pj_Cis *cis, Pj_String *out)
{
pj_scan_get_until(&scanner_, &cis->cis_, out);
}
void get_until_ch(int until_ch, Pj_String *out)
{
pj_scan_get_until_ch(&scanner_, until_ch, out);
}
void get_until_chr(const char *spec, Pj_String *out)
{
pj_scan_get_until_chr(&scanner_, spec, out);
}
void advance_n(unsigned N, bool skip_ws=true)
{
pj_scan_advance_n(&scanner_, N, skip_ws);
}
int strcmp(const char *s, int len)
{
return pj_scan_strcmp(&scanner_, s, len);
}
int stricmp(const char *s, int len)
{
return pj_scan_stricmp(&scanner_, s, len);
}
void skip_ws()
{
pj_scan_skip_whitespace(&scanner_);
}
void save_state(State *state) const
{
pj_scan_save_state(&scanner_, state);
}
void restore_state(State *state)
{
pj_scan_restore_state(&scanner_, state);
}
int get_pos_line() const
{
return scanner_.line;
}
int get_pos_col() const
{
return pj_scan_get_col(&scanner_);
}
private:
pj_scanner scanner_;
};
#endif /* __PJPP_SCANNER_HPP__ */

View File

@@ -0,0 +1,443 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_SOCK_HPP__
#define __PJPP_SOCK_HPP__
#include <pj/sock.h>
#include <pj/string.h>
class Pj_Event_Handler;
//
// Base class for address.
//
class Pj_Addr
{
};
//
// Internet address.
//
class Pj_Inet_Addr : public pj_sockaddr_in, public Pj_Addr
{
public:
//
// Get port number.
//
pj_uint16_t get_port_number() const
{
return pj_sockaddr_in_get_port(this);
}
//
// Set port number.
//
void set_port_number(pj_uint16_t port)
{
sin_family = PJ_AF_INET;
pj_sockaddr_in_set_port(this, port);
}
//
// Get IP address.
//
pj_uint32_t get_ip_address() const
{
return pj_sockaddr_in_get_addr(this).s_addr;
}
//
// Get address string.
//
const char *get_address() const
{
return pj_inet_ntoa(sin_addr);
}
//
// Set IP address.
//
void set_ip_address(pj_uint32_t addr)
{
sin_family = PJ_AF_INET;
pj_sockaddr_in_set_addr(this, addr);
}
//
// Set address.
//
pj_status_t set_address(const pj_str_t *addr)
{
return pj_sockaddr_in_set_str_addr(this, addr);
}
//
// Set address.
//
pj_status_t set_address(const char *addr)
{
pj_str_t s;
return pj_sockaddr_in_set_str_addr(this, pj_cstr(&s, addr));
}
//
// Compare for equality.
//
bool operator==(const Pj_Inet_Addr &rhs) const
{
return sin_family == rhs.sin_family &&
sin_addr.s_addr == rhs.sin_addr.s_addr &&
sin_port == rhs.sin_port;
}
private:
//
// Dummy length used in pj_ioqueue_recvfrom() etc
//
friend class Pj_Event_Handler;
friend class Pj_Socket;
friend class Pj_Sock_Stream;
friend class Pj_Sock_Dgram;
int addrlen_;
};
//
// Socket base class.
//
// Note:
// socket will not automatically be closed on destructor.
//
class Pj_Socket
{
public:
//
// Default constructor.
//
Pj_Socket()
: sock_(PJ_INVALID_SOCKET)
{
}
//
// Initialize from a socket handle.
//
explicit Pj_Socket(pj_sock_t sock)
: sock_(sock)
{
}
//
// Copy constructor.
//
Pj_Socket(const Pj_Socket &rhs)
: sock_(rhs.sock_)
{
}
//
// Destructor will not close the socket.
// You must call close() explicitly.
//
~Pj_Socket()
{
}
//
// Set socket handle.
//
void set_handle(pj_sock_t sock)
{
sock_ = sock;
}
//
// Get socket handle.
//
pj_sock_t get_handle() const
{
return sock_;
}
//
// Get socket handle.
//
pj_sock_t& get_handle()
{
return sock_;
}
//
// See if the socket is valid.
//
bool is_valid() const
{
return sock_ != PJ_INVALID_SOCKET;
}
//
// Create the socket.
//
pj_status_t create(int af, int type, int proto)
{
return pj_sock_socket(af, type, proto, &sock_);
}
//
// Bind socket.
//
pj_status_t bind(const Pj_Inet_Addr &addr)
{
return pj_sock_bind(sock_, &addr, sizeof(Pj_Inet_Addr));
}
//
// Close socket.
//
pj_status_t close()
{
pj_sock_close(sock_);
}
//
// Get peer socket name.
//
pj_status_t getpeername(Pj_Inet_Addr *addr)
{
return pj_sock_getpeername(sock_, addr, &addr->addrlen_);
}
//
// getsockname
//
pj_status_t getsockname(Pj_Inet_Addr *addr)
{
return pj_sock_getsockname(sock_, addr, &addr->addrlen_);
}
//
// getsockopt.
//
pj_status_t getsockopt(pj_uint16_t level, pj_uint16_t optname,
void *optval, int *optlen)
{
return pj_sock_getsockopt(sock_, level, optname, optval, optlen);
}
//
// setsockopt
//
pj_status_t setsockopt(pj_uint16_t level, pj_uint16_t optname,
const void *optval, int optlen)
{
return pj_sock_setsockopt(sock_, level, optname, optval, optlen);
}
//
// receive data.
//
pj_ssize_t recv(void *buf, pj_size_t len, int flag = 0)
{
pj_ssize_t bytes = len;
if (pj_sock_recv(sock_, buf, &bytes, flag) != PJ_SUCCESS)
return -1;
return bytes;
}
//
// send data.
//
pj_ssize_t send(const void *buf, pj_ssize_t len, int flag = 0)
{
pj_ssize_t bytes = len;
if (pj_sock_send(sock_, buf, &bytes, flag) != PJ_SUCCESS)
return -1;
return bytes;
}
//
// connect.
//
pj_status_t connect(const Pj_Inet_Addr &addr)
{
return pj_sock_connect(sock_, &addr, sizeof(Pj_Inet_Addr));
}
//
// assignment.
//
Pj_Socket &operator=(const Pj_Socket &rhs)
{
sock_ = rhs.sock_;
return *this;
}
protected:
friend class Pj_Event_Handler;
pj_sock_t sock_;
};
#if PJ_HAS_TCP
//
// Stream socket.
//
class Pj_Sock_Stream : public Pj_Socket
{
public:
//
// Default constructor.
//
Pj_Sock_Stream()
{
}
//
// Initialize from a socket handle.
//
explicit Pj_Sock_Stream(pj_sock_t sock)
: Pj_Socket(sock)
{
}
//
// Copy constructor.
//
Pj_Sock_Stream(const Pj_Sock_Stream &rhs) : Pj_Socket(rhs)
{
}
//
// Assignment.
//
Pj_Sock_Stream &operator=(const Pj_Sock_Stream &rhs)
{
sock_ = rhs.sock_;
return *this;
}
//
// listen()
//
pj_status_t listen(int backlog = 5)
{
return pj_sock_listen(sock_, backlog);
}
//
// blocking accept()
//
Pj_Sock_Stream accept(Pj_Inet_Addr *remote_addr = NULL)
{
pj_sock_t newsock;
int *addrlen = remote_addr ? &remote_addr->addrlen_ : NULL;
pj_status_t status;
status = pj_sock_accept(sock_, &newsock, remote_addr, addrlen);
if (status != PJ_SUCCESS)
return Pj_Sock_Stream(-1);
return Pj_Sock_Stream(newsock);
}
//
// shutdown()
//
pj_status_t shutdown(int how = PJ_SHUT_RDWR)
{
return pj_sock_shutdown(sock_, how);
}
};
#endif
//
// Datagram socket.
//
class Pj_Sock_Dgram : public Pj_Socket
{
public:
//
// Default constructor.
//
Pj_Sock_Dgram()
{
}
//
// Initialize from a socket handle.
//
explicit Pj_Sock_Dgram(pj_sock_t sock)
: Pj_Socket(sock)
{
}
//
// Copy constructor.
//
Pj_Sock_Dgram(const Pj_Sock_Dgram &rhs)
: Pj_Socket(rhs)
{
}
//
// Assignment.
//
Pj_Sock_Dgram &operator=(const Pj_Sock_Dgram &rhs)
{
Pj_Socket::operator =(rhs);
return *this;
}
//
// recvfrom()
//
pj_ssize_t recvfrom( void *buf, pj_size_t len, int flag = 0,
Pj_Inet_Addr *fromaddr = NULL)
{
pj_ssize_t bytes = len;
int *addrlen = fromaddr ? &fromaddr->addrlen_ : NULL;
if (pj_sock_recvfrom( sock_, buf, &bytes, flag,
fromaddr, addrlen) != PJ_SUCCESS)
{
return -1;
}
return bytes;
}
//
// sendto()
//
pj_ssize_t sendto( const void *buf, pj_size_t len, int flag,
const Pj_Inet_Addr &addr)
{
pj_ssize_t bytes = len;
if (pj_sock_sendto( sock_, buf, &bytes, flag,
&addr, sizeof(pj_sockaddr_in)) != PJ_SUCCESS)
{
return -1;
}
return bytes;
}
};
#endif /* __PJPP_SOCK_HPP__ */

View File

@@ -0,0 +1,467 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_STRING_HPP__
#define __PJPP_STRING_HPP__
#include <pj/string.h>
#include <pj++/pool.hpp>
#include <pj/assert.h>
//
// String wrapper class for pj_str_t.
//
class Pj_String : public pj_str_t
{
public:
//
// Default constructor.
//
Pj_String()
{
pj_assert(sizeof(Pj_String) == sizeof(pj_str_t));
ptr=NULL;
slen=0;
}
//
// Construct the buffer from a char* (use with care)
//
Pj_String(char *str)
{
set(str);
}
//
// Construct from a const char*.
//
Pj_String(Pj_Pool &pool, const char *src)
{
set(pool, src);
}
//
// Construct from pj_str_t&.
//
explicit Pj_String(pj_str_t &s)
{
ptr = s.ptr;
slen = s.slen;
}
//
// Construct from const pj_str_t& (use with care!).
//
explicit Pj_String(const pj_str_t &s)
{
ptr = (char*)s.ptr;
slen = s.slen;
}
//
// Construct by copying from const pj_str_t*.
//
Pj_String(Pj_Pool &pool, const pj_str_t *s)
{
set(pool, s);
}
//
// Construct by copying from Pj_String
//
Pj_String(Pj_Pool &pool, const Pj_String &rhs)
{
set(pool, rhs);
}
//
// Construct from another Pj_String, use with care!
//
explicit Pj_String(const Pj_String &rhs)
{
ptr = rhs.ptr;
slen = rhs.slen;
}
//
// Construct from a char* and a length.
//
Pj_String(char *str, pj_size_t len)
{
set(str, len);
}
//
// Construct from pair of pointer.
//
Pj_String(char *begin, char *end)
{
pj_strset3(this, begin, end);
}
//
// You can cast Pj_String to pj_str_t*
//
operator pj_str_t*()
{
return this;
}
//
// You can cast const Pj_String to const pj_str_t*
//
operator const pj_str_t*() const
{
return this;
}
//
// Get the length of the string.
//
pj_size_t length() const
{
return pj_strlen(this);
}
//
// Get the length of the string.
//
pj_size_t size() const
{
return length();
}
//
// Get the string buffer.
//
const char *buf() const
{
return ptr;
}
//
// Initialize buffer from char*.
//
void set(char *str)
{
pj_strset2(this, str);
}
//
// Initialize by copying from a const char*.
//
void set(Pj_Pool &pool, const char *s)
{
pj_strdup2(pool, this, s);
}
//
// Initialize from pj_str_t*.
//
void set(pj_str_t *s)
{
pj_strassign(this, s);
}
//
// Initialize by copying from const pj_str_t*.
//
void set(Pj_Pool &pool, const pj_str_t *s)
{
pj_strdup(pool, this, s);
}
//
// Initialize from char* and length.
//
void set(char *str, pj_size_t len)
{
pj_strset(this, str, len);
}
//
// Initialize from pair of pointers.
//
void set(char *begin, char *end)
{
pj_strset3(this, begin, end);
}
//
// Initialize from other Pj_String.
//
void set(Pj_String &rhs)
{
pj_strassign(this, &rhs);
}
//
// Initialize by copying from a Pj_String*.
//
void set(Pj_Pool &pool, const Pj_String *s)
{
pj_strdup(pool, this, s);
}
//
// Initialize by copying from other Pj_String.
//
void set(Pj_Pool &pool, const Pj_String &s)
{
pj_strdup(pool, this, &s);
}
//
// Copy the contents of other string.
//
void strcpy(const pj_str_t *s)
{
pj_strcpy(this, s);
}
//
// Copy the contents of other string.
//
void strcpy(const Pj_String &rhs)
{
pj_strcpy(this, &rhs);
}
//
// Copy the contents of other string.
//
void strcpy(const char *s)
{
pj_strcpy2(this, s);
}
//
// Compare string.
//
int strcmp(const char *s) const
{
return pj_strcmp2(this, s);
}
//
// Compare string.
//
int strcmp(const pj_str_t *s) const
{
return pj_strcmp(this, s);
}
//
// Compare string.
//
int strcmp(const Pj_String &rhs) const
{
return pj_strcmp(this, &rhs);
}
//
// Compare string.
//
int strncmp(const char *s, pj_size_t len) const
{
return pj_strncmp2(this, s, len);
}
//
// Compare string.
//
int strncmp(const pj_str_t *s, pj_size_t len) const
{
return pj_strncmp(this, s, len);
}
//
// Compare string.
//
int strncmp(const Pj_String &rhs, pj_size_t len) const
{
return pj_strncmp(this, &rhs, len);
}
//
// Compare string.
//
int stricmp(const char *s) const
{
return pj_stricmp2(this, s);
}
//
// Compare string.
//
int stricmp(const pj_str_t *s) const
{
return pj_stricmp(this, s);
}
//
// Compare string.
//
int stricmp(const Pj_String &rhs) const
{
return stricmp(&rhs);
}
//
// Compare string.
//
int strnicmp(const char *s, pj_size_t len) const
{
return pj_strnicmp2(this, s, len);
}
//
// Compare string.
//
int strnicmp(const pj_str_t *s, pj_size_t len) const
{
return pj_strnicmp(this, s, len);
}
//
// Compare string.
//
int strnicmp(const Pj_String &rhs, pj_size_t len) const
{
return strnicmp(&rhs, len);
}
//
// Compare contents for equality.
//
bool operator==(const char *s) const
{
return strcmp(s) == 0;
}
//
// Compare contents for equality.
//
bool operator==(const pj_str_t *s) const
{
return strcmp(s) == 0;
}
//
// Compare contents for equality.
//
bool operator==(const Pj_String &rhs) const
{
return pj_strcmp(this, &rhs) == 0;
}
//
// Assign from char*
//
Pj_String& operator=(char *s)
{
set(s);
return *this;
}
///
// Assign from another Pj_String, use with care!
//
Pj_String& operator=(const Pj_String &rhs)
{
ptr = rhs.ptr;
slen = rhs.slen;
return *this;
}
//
// Find a character in the string.
//
char *strchr(int chr)
{
return pj_strchr(this, chr);
}
//
// Find a character in the string.
//
char *find(int chr)
{
return strchr(chr);
}
//
// Concatenate string.
//
void strcat(const Pj_String &rhs)
{
pj_strcat(this, &rhs);
}
//
// Left trim.
//
void ltrim()
{
pj_strltrim(this);
}
//
// Right trim.
//
void rtrim()
{
pj_strrtrim(this);
}
//
// Left and right trim.
//
void trim()
{
pj_strtrim(this);
}
//
// Convert to unsigned long.
//
unsigned long to_ulong() const
{
return pj_strtoul(this);
}
//
// Convert from unsigned long.
//
void from_ulong(unsigned long value)
{
slen = pj_utoa(value, ptr);
}
//
// Convert from unsigned long with padding.
//
void from_ulong_with_pad(unsigned long value, int min_dig=0, int pad=' ')
{
slen = pj_utoa_pad(value, ptr, min_dig, pad);
}
};
#endif /* __PJPP_STRING_HPP__ */

View File

@@ -0,0 +1,197 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_TIMER_HPP__
#define __PJPP_TIMER_HPP__
#include <pj/timer.h>
#include <pj++/types.hpp>
#include <pj/assert.h>
#include <pj++/lock.hpp>
class Pj_Timer_Heap;
//////////////////////////////////////////////////////////////////////////////
// Timer entry.
//
// How to use:
// Derive class from Pj_Timer_Entry and override on_timeout().
// Scheduler timer in Pj_Timer_Heap.
//
class Pj_Timer_Entry : public Pj_Object
{
friend class Pj_Timer_Heap;
public:
//
// Default constructor.
//
Pj_Timer_Entry()
{
entry_.user_data = this;
entry_.cb = &timer_heap_callback;
}
//
// Destructor, do nothing.
//
~Pj_Timer_Entry()
{
}
//
// Override this to get the timeout notification.
//
virtual void on_timeout(int id) = 0;
private:
pj_timer_entry entry_;
static void timer_heap_callback(pj_timer_heap_t*, pj_timer_entry *e)
{
Pj_Timer_Entry *entry = (Pj_Timer_Entry*) e->user_data;
entry->on_timeout(e->id);
}
};
//////////////////////////////////////////////////////////////////////////////
// Timer heap.
//
class Pj_Timer_Heap : public Pj_Object
{
public:
//
// Default constructor.
//
Pj_Timer_Heap()
: ht_(NULL)
{
}
//
// Construct timer heap.
//
Pj_Timer_Heap(Pj_Pool *pool, pj_size_t initial_count)
: ht_(NULL)
{
create(pool, initial_count);
}
//
// Destructor.
//
~Pj_Timer_Heap()
{
destroy();
}
//
// Create
//
pj_status_t create(Pj_Pool *pool, pj_size_t initial_count)
{
destroy();
return pj_timer_heap_create(pool->pool_(), initial_count, &ht_);
}
//
// Destroy
//
void destroy()
{
if (ht_) {
pj_timer_heap_destroy(ht_);
ht_ = NULL;
}
}
//
// Get pjlib compatible timer heap object.
//
pj_timer_heap_t *get_timer_heap()
{
return ht_;
}
//
// Set the lock object.
//
void set_lock( Pj_Lock *lock, bool auto_delete )
{
pj_timer_heap_set_lock( ht_, lock->pj_lock_t_(), auto_delete);
}
//
// Set maximum number of timed out entries to be processed per poll.
//
unsigned set_max_timed_out_per_poll(unsigned count)
{
return pj_timer_heap_set_max_timed_out_per_poll(ht_, count);
}
//
// Schedule a timer.
//
bool schedule( Pj_Timer_Entry *ent, const Pj_Time_Val &delay,
int id)
{
ent->entry_.id = id;
return pj_timer_heap_schedule(ht_, &ent->entry_, &delay) == 0;
}
//
// Cancel a timer.
//
bool cancel(Pj_Timer_Entry *ent)
{
return pj_timer_heap_cancel(ht_, &ent->entry_) == 1;
}
//
// Get current number of timers
//
pj_size_t count()
{
return pj_timer_heap_count(ht_);
}
//
// Get the earliest time.
// Return false if no timer is found.
//
bool earliest_time(Pj_Time_Val *t)
{
return pj_timer_heap_earliest_time(ht_, t) == PJ_SUCCESS;
}
//
// Poll the timer.
// Return number of timed out entries has been called.
//
unsigned poll(Pj_Time_Val *next_delay = NULL)
{
return pj_timer_heap_poll(ht_, next_delay);
}
private:
pj_timer_heap_t *ht_;
};
#endif /* __PJPP_TIMER_HPP__ */

View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_TREE_HPP__
#define __PJPP_TREE_HPP__
#include <pj/rbtree.h>
//
// Tree.
//
class PJ_Tree
{
public:
typedef pj_rbtree_comp Comp;
class iterator;
class reverse_iterator;
class Node : private pj_rbtree_node
{
friend class PJ_Tree;
friend class iterator;
friend class reverse_iterator;
public:
Node() {}
explicit Node(void *data) { user_data = data; }
void set_user_data(void *data) { user_data = data; }
void *get_user_data() const { return user_data; }
};
class iterator
{
public:
iterator() {}
iterator(const iterator &rhs) : tr_(rhs.tr_), nd_(rhs.nd_) {}
iterator(pj_rbtree *tr, pj_rbtree_node *nd) : tr_(tr), nd_(nd) {}
Node *operator*() { return (Node*)nd_; }
bool operator==(const iterator &rhs) const { return tr_==rhs.tr_ && nd_==rhs.nd_; }
iterator &operator=(const iterator &rhs) { tr_=rhs.tr_; nd_=rhs.nd_; return *this; }
void operator++() { nd_=pj_rbtree_next(tr_, nd_); }
void operator--() { nd_=pj_rbtree_prev(tr_, nd_); }
protected:
pj_rbtree *tr_;
pj_rbtree_node *nd_;
};
class reverse_iterator : public iterator
{
public:
reverse_iterator() {}
reverse_iterator(const reverse_iterator &it) : iterator(it) {}
reverse_iterator(pj_rbtree *t, pj_rbtree_node *n) : iterator(t, n) {}
reverse_iterator &operator=(const reverse_iterator &rhs) { iterator::operator=(rhs); return *this; }
Node *operator*() { return (Node*)nd_; }
bool operator==(const reverse_iterator &rhs) const { return iterator::operator==(rhs); }
void operator++() { nd_=pj_rbtree_prev(tr_, nd_); }
void operator--() { nd_=pj_rbtree_next(tr_, nd_); }
};
explicit PJ_Tree(Comp *comp) { pj_rbtree_init(&t_, comp); }
iterator begin()
{
return iterator(&t_, pj_rbtree_first(&t_));
}
iterator end()
{
return iterator(&t_, NULL);
}
reverse_iterator rbegin()
{
return reverse_iterator(&t_, pj_rbtree_last(&t_));
}
reverse_iterator rend()
{
return reverse_iterator(&t_, NULL);
}
bool insert(Node *node)
{
return pj_rbtree_insert(&t_, node)==0 ? true : false;
}
Node *find(const void *key)
{
return (Node*)pj_rbtree_find(&t_, key);
}
Node *erase(Node *node)
{
return (Node*)pj_rbtree_erase(&t_, node);
}
unsigned max_height(Node *node=NULL)
{
return pj_rbtree_max_height(&t_, node);
}
unsigned min_height(Node *node=NULL)
{
return pj_rbtree_min_height(&t_, node);
}
private:
pj_rbtree t_;
};
#endif /* __PJPP_TREE_HPP__ */

View File

@@ -0,0 +1,174 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJPP_TYPES_HPP__
#define __PJPP_TYPES_HPP__
#include <pj/types.h>
class Pj_Pool;
class Pj_Socket ;
class Pj_Lock;
//
// PJLIB initializer.
//
class Pjlib
{
public:
Pjlib()
{
pj_init();
}
};
//
// Class Pj_Object is declared in pool.hpp
//
//
// Time value wrapper.
//
class Pj_Time_Val : public pj_time_val
{
public:
Pj_Time_Val()
{
}
Pj_Time_Val(long init_sec, long init_msec)
{
sec = init_sec;
msec = init_msec;
}
Pj_Time_Val(const Pj_Time_Val &rhs)
{
sec=rhs.sec;
msec=rhs.msec;
}
explicit Pj_Time_Val(const pj_time_val &tv)
{
sec = tv.sec;
msec = tv.msec;
}
long get_sec() const
{
return sec;
}
long get_msec() const
{
return msec;
}
void set_sec (long s)
{
sec = s;
}
void set_msec(long ms)
{
msec = ms;
normalize();
}
long to_msec() const
{
return PJ_TIME_VAL_MSEC((*this));
}
bool operator == (const Pj_Time_Val &rhs) const
{
return PJ_TIME_VAL_EQ((*this), rhs);
}
bool operator > (const Pj_Time_Val &rhs) const
{
return PJ_TIME_VAL_GT((*this), rhs);
}
bool operator >= (const Pj_Time_Val &rhs) const
{
return PJ_TIME_VAL_GTE((*this), rhs);
}
bool operator < (const Pj_Time_Val &rhs) const
{
return PJ_TIME_VAL_LT((*this), rhs);
}
bool operator <= (const Pj_Time_Val &rhs) const
{
return PJ_TIME_VAL_LTE((*this), rhs);
}
Pj_Time_Val & operator = (const Pj_Time_Val &rhs)
{
sec = rhs.sec;
msec = rhs.msec;
return *this;
}
Pj_Time_Val & operator += (const Pj_Time_Val &rhs)
{
PJ_TIME_VAL_ADD((*this), rhs);
return *this;
}
Pj_Time_Val & operator -= (const Pj_Time_Val &rhs)
{
PJ_TIME_VAL_SUB((*this), rhs);
return *this;
}
/* Must include os.hpp to use these, otherwise unresolved in linking */
inline pj_status_t gettimeofday();
inline pj_parsed_time decode();
inline pj_status_t encode(const pj_parsed_time *pt);
inline pj_status_t to_gmt();
inline pj_status_t to_local();
private:
void normalize()
{
pj_time_val_normalize(this);
}
};
//
// Macro to declare common object comparison operators.
//
#define PJ_DECLARE_OPERATORS(rhs_type) \
bool operator!=(rhs_type rhs) const { \
return !operator==(rhs); } \
bool operator<=(rhs_type rhs) const { \
return operator<(rhs) || operator==(rhs); } \
bool operator>(rhs_type rhs) const { \
return !operator<=(rhs); } \
bool operator>=(rhs_type rhs) const { \
return !operator<(rhs); }
#endif /* __PJPP_TYPES_HPP__ */

View File

@@ -0,0 +1,598 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_ASYNCSOCK_H__
#define __PJ_ASYNCSOCK_H__
/**
* @file activesock.h
* @brief Active socket
*/
#include <pj/ioqueue.h>
#include <pj/sock.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_ACTIVESOCK Active socket I/O
* @brief Active socket performs active operations on socket.
* @ingroup PJ_IO
* @{
*
* Active socket is a higher level abstraction to the ioqueue. It provides
* automation to socket operations which otherwise would have to be done
* manually by the applications. For example with socket recv(), recvfrom(),
* and accept() operations, application only needs to invoke these
* operation once, and it will be notified whenever data or incoming TCP
* connection (in the case of accept()) arrives.
*/
/**
* This opaque structure describes the active socket.
*/
typedef struct pj_activesock_t pj_activesock_t;
/**
* This structure contains the callbacks to be called by the active socket.
*/
typedef struct pj_activesock_cb
{
/**
* This callback is called when a data arrives as the result of
* pj_activesock_start_read().
*
* @param asock The active socket.
* @param data The buffer containing the new data, if any. If
* the status argument is non-PJ_SUCCESS, this
* argument may be NULL.
* @param size The length of data in the buffer.
* @param status The status of the read operation. This may contain
* non-PJ_SUCCESS for example when the TCP connection
* has been closed. In this case, the buffer may
* contain left over data from previous callback which
* the application may want to process.
* @param remainder If application wishes to leave some data in the
* buffer (common for TCP applications), it should
* move the remainder data to the front part of the
* buffer and set the remainder length here. The value
* of this parameter will be ignored for datagram
* sockets.
*
* @return PJ_TRUE if further read is desired, and PJ_FALSE
* when application no longer wants to receive data.
* Application may destroy the active socket in the
* callback and return PJ_FALSE here.
*/
pj_bool_t (*on_data_read)(pj_activesock_t *asock,
void *data,
pj_size_t size,
pj_status_t status,
pj_size_t *remainder);
/**
* This callback is called when a packet arrives as the result of
* pj_activesock_start_recvfrom().
*
* @param asock The active socket.
* @param data The buffer containing the packet, if any. If
* the status argument is non-PJ_SUCCESS, this
* argument will be set to NULL.
* @param size The length of packet in the buffer. If
* the status argument is non-PJ_SUCCESS, this
* argument will be set to zero.
* @param src_addr Source address of the packet.
* @param addr_len Length of the source address.
* @param status This contains
*
* @return PJ_TRUE if further read is desired, and PJ_FALSE
* when application no longer wants to receive data.
* Application may destroy the active socket in the
* callback and return PJ_FALSE here.
*/
pj_bool_t (*on_data_recvfrom)(pj_activesock_t *asock,
void *data,
pj_size_t size,
const pj_sockaddr_t *src_addr,
int addr_len,
pj_status_t status);
/**
* This callback is called when data has been sent.
*
* @param asock The active socket.
* @param send_key Key associated with the send operation.
* @param sent If value is positive non-zero it indicates the
* number of data sent. When the value is negative,
* it contains the error code which can be retrieved
* by negating the value (i.e. status=-sent).
*
* @return Application may destroy the active socket in the
* callback and return PJ_FALSE here.
*/
pj_bool_t (*on_data_sent)(pj_activesock_t *asock,
pj_ioqueue_op_key_t *send_key,
pj_ssize_t sent);
/**
* This callback is called when new connection arrives as the result
* of pj_activesock_start_accept(). If the status of accept operation is
* needed use on_accept_complete2 instead of this callback.
*
* @param asock The active socket.
* @param newsock The new incoming socket.
* @param src_addr The source address of the connection.
* @param addr_len Length of the source address.
*
* @return PJ_TRUE if further accept() is desired, and PJ_FALSE
* when application no longer wants to accept incoming
* connection. Application may destroy the active socket
* in the callback and return PJ_FALSE here.
*/
pj_bool_t (*on_accept_complete)(pj_activesock_t *asock,
pj_sock_t newsock,
const pj_sockaddr_t *src_addr,
int src_addr_len);
/**
* This callback is called when new connection arrives as the result
* of pj_activesock_start_accept().
*
* @param asock The active socket.
* @param newsock The new incoming socket.
* @param src_addr The source address of the connection.
* @param addr_len Length of the source address.
* @param status The status of the accept operation. This may contain
* non-PJ_SUCCESS for example when the TCP listener is in
* bad state for example on iOS platform after the
* application waking up from background.
*
* @return PJ_TRUE if further accept() is desired, and PJ_FALSE
* when application no longer wants to accept incoming
* connection. Application may destroy the active socket
* in the callback and return PJ_FALSE here.
*/
pj_bool_t (*on_accept_complete2)(pj_activesock_t *asock,
pj_sock_t newsock,
const pj_sockaddr_t *src_addr,
int src_addr_len,
pj_status_t status);
/**
* This callback is called when pending connect operation has been
* completed.
*
* @param asock The active socket.
* @param status The connection result. If connection has been
* successfully established, the status will contain
* PJ_SUCCESS.
*
* @return Application may destroy the active socket in the
* callback and return PJ_FALSE here.
*/
pj_bool_t (*on_connect_complete)(pj_activesock_t *asock,
pj_status_t status);
} pj_activesock_cb;
/**
* Settings that can be given during active socket creation. Application
* must initialize this structure with #pj_activesock_cfg_default().
*/
typedef struct pj_activesock_cfg
{
/**
* Optional group lock to be assigned to the ioqueue key.
*/
pj_grp_lock_t *grp_lock;
/**
* Number of concurrent asynchronous operations that is to be supported
* by the active socket. This value only affects socket receive and
* accept operations -- the active socket will issue one or more
* asynchronous read and accept operations based on the value of this
* field. Setting this field to more than one will allow more than one
* incoming data or incoming connections to be processed simultaneously
* on multiprocessor systems, when the ioqueue is polled by more than
* one threads.
*
* The default value is 1.
*/
unsigned async_cnt;
/**
* The ioqueue concurrency to be forced on the socket when it is
* registered to the ioqueue. See #pj_ioqueue_set_concurrency() for more
* info about ioqueue concurrency.
*
* When this value is -1, the concurrency setting will not be forced for
* this socket, and the socket will inherit the concurrency setting of
* the ioqueue. When this value is zero, the active socket will disable
* concurrency for the socket. When this value is +1, the active socket
* will enable concurrency for the socket.
*
* The default value is -1.
*/
int concurrency;
/**
* If this option is specified, the active socket will make sure that
* asynchronous send operation with stream oriented socket will only
* call the callback after all data has been sent. This means that the
* active socket will automatically resend the remaining data until
* all data has been sent.
*
* Please note that when this option is specified, it is possible that
* error is reported after partial data has been sent. Also setting
* this will disable the ioqueue concurrency for the socket.
*
* Default value is PJ_TRUE.
*/
pj_bool_t whole_data;
/**
* If this option is specified, set close-on-exec flag for socket.
* This option is only used by #pj_activesock_create_udp()
*
* Default value is PJ_TRUE.
*/
pj_bool_t sock_cloexec;
} pj_activesock_cfg;
/**
* Initialize the active socket configuration with the default values.
*
* @param cfg The configuration to be initialized.
*/
PJ_DECL(void) pj_activesock_cfg_default(pj_activesock_cfg *cfg);
/**
* Create the active socket for the specified socket. This will register
* the socket to the specified ioqueue.
*
* @param pool Pool to allocate memory from.
* @param sock The socket handle.
* @param sock_type Specify socket type, either pj_SOCK_DGRAM() or
* pj_SOCK_STREAM(). The active socket needs this
* information to handle connection closure for
* connection oriented sockets.
* @param ioqueue The ioqueue to use.
* @param opt Optional settings. When this setting is not specifed,
* the default values will be used.
* @param cb Pointer to structure containing application
* callbacks.
* @param user_data Arbitrary user data to be associated with this
* active socket.
* @param p_asock Pointer to receive the active socket instance.
*
* @return PJ_SUCCESS if the operation has been successful,
* or the appropriate error code on failure.
*/
PJ_DECL(pj_status_t) pj_activesock_create(pj_pool_t *pool,
pj_sock_t sock,
int sock_type,
const pj_activesock_cfg *opt,
pj_ioqueue_t *ioqueue,
const pj_activesock_cb *cb,
void *user_data,
pj_activesock_t **p_asock);
/**
* Create UDP socket descriptor, bind it to the specified address, and
* create the active socket for the socket descriptor.
*
* @param pool Pool to allocate memory from.
* @param addr Specifies the address family of the socket and the
* address where the socket should be bound to. If
* this argument is NULL, then AF_INET is assumed and
* the socket will be bound to any addresses and port.
* @param ioqueue The ioqueue.
* @param opt Optional settings. When this setting is not specifed,
* the default values will be used.
* @param cb Pointer to structure containing application
* callbacks.
* @param user_data Arbitrary user data to be associated with this
* active socket.
* @param p_asock Pointer to receive the active socket instance.
* @param bound_addr If this argument is specified, it will be filled with
* the bound address on return.
*
* @return PJ_SUCCESS if the operation has been successful,
* or the appropriate error code on failure.
*/
PJ_DECL(pj_status_t) pj_activesock_create_udp(pj_pool_t *pool,
const pj_sockaddr *addr,
const pj_activesock_cfg *opt,
pj_ioqueue_t *ioqueue,
const pj_activesock_cb *cb,
void *user_data,
pj_activesock_t **p_asock,
pj_sockaddr *bound_addr);
/**
* Close the active socket. This will unregister the socket from the
* ioqueue and ultimately close the socket.
*
* @param asock The active socket.
*
* @return PJ_SUCCESS if the operation has been successful,
* or the appropriate error code on failure.
*/
PJ_DECL(pj_status_t) pj_activesock_close(pj_activesock_t *asock);
#if (defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0) || \
defined(DOXYGEN)
/**
* Set iPhone OS background mode setting. Setting to 1 will enable TCP
* active socket to receive incoming data when application is in the
* background. Setting to 0 will disable it. Default value of this
* setting is PJ_ACTIVESOCK_TCP_IPHONE_OS_BG.
*
* This API is only available if PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT
* is set to non-zero.
*
* @param asock The active socket.
* @param val The value of background mode setting.
*
*/
PJ_DECL(void) pj_activesock_set_iphone_os_bg(pj_activesock_t *asock,
int val);
/**
* Enable/disable support for iPhone OS background mode. This setting
* will apply globally and will affect any active sockets created
* afterwards, if you want to change the setting for a particular
* active socket, use #pj_activesock_set_iphone_os_bg() instead.
* By default, this setting is enabled.
*
* This API is only available if PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT
* is set to non-zero.
*
* @param val The value of global background mode setting.
*
*/
PJ_DECL(void) pj_activesock_enable_iphone_os_bg(pj_bool_t val);
#endif
/**
* Associate arbitrary data with the active socket. Application may
* inspect this data in the callbacks and associate it with higher
* level processing.
*
* @param asock The active socket.
* @param user_data The user data to be associated with the active
* socket.
*
* @return PJ_SUCCESS if the operation has been successful,
* or the appropriate error code on failure.
*/
PJ_DECL(pj_status_t) pj_activesock_set_user_data(pj_activesock_t *asock,
void *user_data);
/**
* Retrieve the user data previously associated with this active
* socket.
*
* @param asock The active socket.
*
* @return The user data.
*/
PJ_DECL(void*) pj_activesock_get_user_data(pj_activesock_t *asock);
/**
* Starts read operation on this active socket. This function will create
* \a async_cnt number of buffers (the \a async_cnt parameter was given
* in \a pj_activesock_create() function) where each buffer is \a buff_size
* long. The buffers are allocated from the specified \a pool. Once the
* buffers are created, it then issues \a async_cnt number of asynchronous
* \a recv() operations to the socket and returns back to caller. Incoming
* data on the socket will be reported back to application via the
* \a on_data_read() callback.
*
* Application only needs to call this function once to initiate read
* operations. Further read operations will be done automatically by the
* active socket when \a on_data_read() callback returns non-zero.
*
* @param asock The active socket.
* @param pool Pool used to allocate buffers for incoming data.
* @param buff_size The size of each buffer, in bytes.
* @param flags Flags to be given to pj_ioqueue_recv().
*
* @return PJ_SUCCESS if the operation has been successful,
* or the appropriate error code on failure.
*/
PJ_DECL(pj_status_t) pj_activesock_start_read(pj_activesock_t *asock,
pj_pool_t *pool,
unsigned buff_size,
pj_uint32_t flags);
/**
* Same as #pj_activesock_start_read(), except that the application
* supplies the buffers for the read operation so that the acive socket
* does not have to allocate the buffers.
*
* @param asock The active socket.
* @param pool Pool used to allocate buffers for incoming data.
* @param buff_size The size of each buffer, in bytes.
* @param readbuf Array of packet buffers, each has buff_size size.
* @param flags Flags to be given to pj_ioqueue_recv().
*
* @return PJ_SUCCESS if the operation has been successful,
* or the appropriate error code on failure.
*/
PJ_DECL(pj_status_t) pj_activesock_start_read2(pj_activesock_t *asock,
pj_pool_t *pool,
unsigned buff_size,
void *readbuf[],
pj_uint32_t flags);
/**
* Same as pj_activesock_start_read(), except that this function is used
* only for datagram sockets, and it will trigger \a on_data_recvfrom()
* callback instead.
*
* @param asock The active socket.
* @param pool Pool used to allocate buffers for incoming data.
* @param buff_size The size of each buffer, in bytes.
* @param flags Flags to be given to pj_ioqueue_recvfrom().
*
* @return PJ_SUCCESS if the operation has been successful,
* or the appropriate error code on failure.
*/
PJ_DECL(pj_status_t) pj_activesock_start_recvfrom(pj_activesock_t *asock,
pj_pool_t *pool,
unsigned buff_size,
pj_uint32_t flags);
/**
* Same as #pj_activesock_start_recvfrom() except that the recvfrom()
* operation takes the buffer from the argument rather than creating
* new ones.
*
* @param asock The active socket.
* @param pool Pool used to allocate buffers for incoming data.
* @param buff_size The size of each buffer, in bytes.
* @param readbuf Array of packet buffers, each has buff_size size.
* @param flags Flags to be given to pj_ioqueue_recvfrom().
*
* @return PJ_SUCCESS if the operation has been successful,
* or the appropriate error code on failure.
*/
PJ_DECL(pj_status_t) pj_activesock_start_recvfrom2(pj_activesock_t *asock,
pj_pool_t *pool,
unsigned buff_size,
void *readbuf[],
pj_uint32_t flags);
/**
* Send data using the socket.
*
* @param asock The active socket.
* @param send_key The operation key to send the data, which is useful
* if application wants to submit multiple pending
* send operations and want to track which exact data
* has been sent in the \a on_data_sent() callback.
* @param data The data to be sent. This data must remain valid
* until the data has been sent.
* @param size The size of the data.
* @param flags Flags to be given to pj_ioqueue_send().
*
*
* @return PJ_SUCCESS if data has been sent immediately, or
* PJ_EPENDING if data cannot be sent immediately. In
* this case the \a on_data_sent() callback will be
* called when data is actually sent. Any other return
* value indicates error condition.
*/
PJ_DECL(pj_status_t) pj_activesock_send(pj_activesock_t *asock,
pj_ioqueue_op_key_t *send_key,
const void *data,
pj_ssize_t *size,
unsigned flags);
/**
* Send datagram using the socket.
*
* @param asock The active socket.
* @param send_key The operation key to send the data, which is useful
* if application wants to submit multiple pending
* send operations and want to track which exact data
* has been sent in the \a on_data_sent() callback.
* @param data The data to be sent. This data must remain valid
* until the data has been sent.
* @param size The size of the data.
* @param flags Flags to be given to pj_ioqueue_send().
* @param addr The destination address.
* @param addr_len The length of the address.
*
* @return PJ_SUCCESS if data has been sent immediately, or
* PJ_EPENDING if data cannot be sent immediately. In
* this case the \a on_data_sent() callback will be
* called when data is actually sent. Any other return
* value indicates error condition.
*/
PJ_DECL(pj_status_t) pj_activesock_sendto(pj_activesock_t *asock,
pj_ioqueue_op_key_t *send_key,
const void *data,
pj_ssize_t *size,
unsigned flags,
const pj_sockaddr_t *addr,
int addr_len);
#if PJ_HAS_TCP
/**
* Starts asynchronous socket accept() operations on this active socket.
* Application must bind the socket before calling this function. This
* function will issue \a async_cnt number of asynchronous \a accept()
* operations to the socket and returns back to caller. Incoming
* connection on the socket will be reported back to application via the
* \a on_accept_complete() callback.
*
* Application only needs to call this function once to initiate accept()
* operations. Further accept() operations will be done automatically by
* the active socket when \a on_accept_complete() callback returns non-zero.
*
* @param asock The active socket.
* @param pool Pool used to allocate some internal data for the
* operation.
*
* @return PJ_SUCCESS if the operation has been successful,
* or the appropriate error code on failure.
*/
PJ_DECL(pj_status_t) pj_activesock_start_accept(pj_activesock_t *asock,
pj_pool_t *pool);
/**
* Starts asynchronous socket connect() operation for this socket. Once
* the connection is done (either successfully or not), the
* \a on_connect_complete() callback will be called.
*
* @param asock The active socket.
* @param pool The pool to allocate some internal data for the
* operation.
* @param remaddr Remote address.
* @param addr_len Length of the remote address.
*
* @return PJ_SUCCESS if connection can be established immediately,
* or PJ_EPENDING if connection cannot be established
* immediately. In this case the \a on_connect_complete()
* callback will be called when connection is complete.
* Any other return value indicates error condition.
*/
PJ_DECL(pj_status_t) pj_activesock_start_connect(pj_activesock_t *asock,
pj_pool_t *pool,
const pj_sockaddr_t *remaddr,
int addr_len);
#endif /* PJ_HAS_TCP */
/**
* @}
*/
PJ_END_DECL
#endif /* __PJ_ASYNCSOCK_H__ */

View File

@@ -0,0 +1,189 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_ADDR_RESOLV_H__
#define __PJ_ADDR_RESOLV_H__
/**
* @file addr_resolv.h
* @brief IP address resolution.
*/
#include <pj/sock.h>
PJ_BEGIN_DECL
/**
* @defgroup pj_addr_resolve Network Address Resolution
* @ingroup PJ_IO
* @{
*
* This module provides function to resolve Internet address of the
* specified host name. To resolve a particular host name, application
* can just call #pj_gethostbyname().
*
* Example:
* <pre>
* ...
* pj_hostent he;
* pj_status_t rc;
* pj_str_t host = pj_str("host.example.com");
*
* rc = pj_gethostbyname( &host, &he);
* if (rc != PJ_SUCCESS) {
* char errbuf[80];
* pj_strerror( rc, errbuf, sizeof(errbuf));
* PJ_LOG(2,("sample", "Unable to resolve host, error=%s", errbuf));
* return rc;
* }
*
* // process address...
* addr.sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
* ...
* </pre>
*
* It's pretty simple really...
*/
/** This structure describes an Internet host address. */
typedef struct pj_hostent
{
char *h_name; /**< The official name of the host. */
char **h_aliases; /**< Aliases list. */
int h_addrtype; /**< Host address type. */
int h_length; /**< Length of address. */
char **h_addr_list; /**< List of addresses. */
} pj_hostent;
/** Shortcut to h_addr_list[0] */
#define h_addr h_addr_list[0]
/**
* This structure describes address information pj_getaddrinfo().
*/
typedef struct pj_addrinfo
{
char ai_canonname[PJ_MAX_HOSTNAME]; /**< Canonical name for host*/
pj_sockaddr ai_addr; /**< Binary address. */
} pj_addrinfo;
/**
* This function fills the structure of type pj_hostent for a given host name.
* For host resolution function that also works with IPv6, please see
* #pj_getaddrinfo().
*
* @param name Host name to resolve. Specifying IPv4 address here
* may fail on some platforms (e.g. Windows)
* @param he The pj_hostent structure to be filled. Note that
* the pointers in this structure points to temporary
* variables which value will be reset upon subsequent
* invocation.
*
* @return PJ_SUCCESS, or the appropriate error codes.
*/
PJ_DECL(pj_status_t) pj_gethostbyname(const pj_str_t *name, pj_hostent *he);
/**
* Resolve the primary IP address of local host.
*
* @param af The desired address family to query. Valid values
* are pj_AF_INET() or pj_AF_INET6().
* @param addr On successful resolution, the address family and address
* part of this socket address will be filled up with the host
* IP address, in network byte order. Other parts of the socket
* address are untouched.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr);
/**
* Get the interface IP address to send data to the specified destination.
*
* @param af The desired address family to query. Valid values
* are pj_AF_INET() or pj_AF_INET6().
* @param dst The destination host.
* @param itf_addr On successful resolution, the address family and address
* part of this socket address will be filled up with the host
* IP address, in network byte order. Other parts of the socket
* address should be ignored.
* @param allow_resolve If \a dst may contain hostname (instead of IP
* address), specify whether hostname resolution should
* be performed. If not, default interface address will
* be returned.
* @param p_dst_addr If not NULL, it will be filled with the IP address of
* the destination host.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_getipinterface(int af,
const pj_str_t *dst,
pj_sockaddr *itf_addr,
pj_bool_t allow_resolve,
pj_sockaddr *p_dst_addr);
/**
* Get the IP address of the default interface. Default interface is the
* interface of the default route.
*
* @param af The desired address family to query. Valid values
* are pj_AF_INET() or pj_AF_INET6().
* @param addr On successful resolution, the address family and address
* part of this socket address will be filled up with the host
* IP address, in network byte order. Other parts of the socket
* address are untouched.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_getdefaultipinterface(int af,
pj_sockaddr *addr);
/**
* This function translates the name of a service location (for example,
* a host name) and returns a set of addresses and associated information
* to be used in creating a socket with which to address the specified
* service.
*
* @param af The desired address family to query. Valid values
* are pj_AF_INET(), pj_AF_INET6(), or pj_AF_UNSPEC().
* @param name Descriptive name or an address string, such as host
* name.
* @param count On input, it specifies the number of elements in
* \a ai array. On output, this will be set with the
* number of address informations found for the
* specified name.
* @param ai Array of address info to be filled with the information
* about the host.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *name,
unsigned *count, pj_addrinfo ai[]);
/** @} */
PJ_END_DECL
#endif /* __PJ_ADDR_RESOLV_H__ */

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_ARRAY_H__
#define __PJ_ARRAY_H__
/**
* @file array.h
* @brief PJLIB Array helper.
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_ARRAY Array helper.
* @ingroup PJ_DS
* @{
*
* This module provides helper to manipulate array of elements of any size.
* It provides most used array operations such as insert, erase, and search.
*/
/**
* Insert value to the array at the given position, and rearrange the
* remaining nodes after the position.
*
* @param array the array.
* @param elem_size the size of the individual element.
* @param count the CURRENT number of elements in the array.
* @param pos the position where the new element is put.
* @param value the value to copy to the new element.
*/
PJ_DECL(void) pj_array_insert( void *array,
unsigned elem_size,
unsigned count,
unsigned pos,
const void *value);
/**
* Erase a value from the array at given position, and rearrange the remaining
* elements post the erased element.
*
* @param array the array.
* @param elem_size the size of the individual element.
* @param count the current number of elements in the array.
* @param pos the index/position to delete.
*/
PJ_DECL(void) pj_array_erase( void *array,
unsigned elem_size,
unsigned count,
unsigned pos);
/**
* Search the first value in the array according to matching function.
*
* @param array the array.
* @param elem_size the individual size of the element.
* @param count the number of elements.
* @param matching the matching function, which MUST return PJ_SUCCESS if
* the specified element match.
* @param result the pointer to the value found.
*
* @return PJ_SUCCESS if value is found, otherwise the error code.
*/
PJ_DECL(pj_status_t) pj_array_find( const void *array,
unsigned elem_size,
unsigned count,
pj_status_t (*matching)(const void *value),
void **result);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJ_ARRAY_H__ */

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_ASSERT_H__
#define __PJ_ASSERT_H__
/**
* @file assert.h
* @brief Assertion macro pj_assert().
*/
#include <pj/config.h>
#include <pj/compat/assert.h>
/**
* @defgroup pj_assert Assertion Macro
* @ingroup PJ_MISC
* @{
*
* Assertion and other helper macros for sanity checking.
*/
/**
* @hideinitializer
* Check during debug build that an expression is true. If the expression
* computes to false during run-time, then the program will stop at the
* offending statements.
* For release build, this macro will not do anything.
*
* @param expr The expression to be evaluated.
*/
#ifndef pj_assert
# define pj_assert(expr) assert(expr)
#endif
/**
* @hideinitializer
* If the expression yields false, assertion will be triggered
* and the current function will return with the specified return value.
*/
// #if defined(PJ_ENABLE_EXTRA_CHECK) && PJ_ENABLE_EXTRA_CHECK != 0
#define PJ_ASSERT_RETURN(expr,retval) \
do { \
if (!(expr)) { pj_assert(expr); return retval; } \
} while (0)
//#else
//# define PJ_ASSERT_RETURN(expr,retval) pj_assert(expr)
//#endif
/**
* @hideinitializer
* If the expression yields false, assertion will be triggered
* and @a exec_on_fail will be executed.
*/
//#if defined(PJ_ENABLE_EXTRA_CHECK) && PJ_ENABLE_EXTRA_CHECK != 0
#define PJ_ASSERT_ON_FAIL(expr,exec_on_fail) \
{ \
pj_assert(expr); \
if (!(expr)) exec_on_fail; \
}
//#else
//# define PJ_ASSERT_ON_FAIL(expr,exec_on_fail) pj_assert(expr)
//#endif
/** @} */
#endif /* __PJ_ASSERT_H__ */

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_ASSERT_H__
#define __PJ_COMPAT_ASSERT_H__
/**
* @file assert.h
* @brief Provides assert() macro.
*/
#if defined(PJ_HAS_ASSERT_H) && PJ_HAS_ASSERT_H != 0
# include <assert.h>
#else
# warning "assert() is not implemented"
# define assert(expr)
#endif
#endif /* __PJ_COMPAT_ASSERT_H__ */

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_CC_ARMCC_H__
#define __PJ_COMPAT_CC_ARMCC_H__
/**
* @file cc_armcc.h
* @brief Describes ARMCC compiler specifics.
*/
#ifndef __ARMCC__
# error "This file is only for armcc!"
#endif
#define PJ_CC_NAME "armcc"
#define PJ_CC_VER_1 (__ARMCC_VERSION/100000)
#define PJ_CC_VER_2 ((__ARMCC_VERSION%100000)/10000)
#define PJ_CC_VER_3 (__ARMCC_VERSION%10000)
#ifdef __cplusplus
# define PJ_INLINE_SPECIFIER inline
#else
# define PJ_INLINE_SPECIFIER static __inline
#endif
#define PJ_THREAD_FUNC
#define PJ_NORETURN
#define PJ_ATTR_NORETURN __attribute__ ((noreturn))
#define PJ_ATTR_MAY_ALIAS __attribute__ ((__may_alias__))
#define PJ_HAS_INT64 1
typedef long long pj_int64_t;
typedef unsigned long long pj_uint64_t;
#define PJ_INT64_FMT "L"
#define PJ_UNREACHED(x)
#endif /* __PJ_COMPAT_CC_ARMCC_H__ */

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2023 Teluu Inc. (http://www.teluu.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_CC_CLANG_H__
#define __PJ_COMPAT_CC_CLANG_H__
/**
* @file cc_clang.h
* @brief Describes CLANG compiler specifics.
*/
#ifndef __clang__
# error "This file is only for clang!"
#endif
#define PJ_CC_NAME "clang"
#define PJ_CC_VER_1 __clang_major__
#define PJ_CC_VER_2 __clang_minor__
#define PJ_CC_VER_3 __clang_patchlevel__
#define PJ_THREAD_FUNC
#define PJ_NORETURN
#define PJ_HAS_INT64 1
#ifdef __STRICT_ANSI__
#include <inttypes.h>
typedef int64_t pj_int64_t;
typedef uint64_t pj_uint64_t;
#define PJ_INLINE_SPECIFIER static __inline
#define PJ_ATTR_NORETURN
#define PJ_ATTR_MAY_ALIAS
#else
typedef long long pj_int64_t;
typedef unsigned long long pj_uint64_t;
#define PJ_INLINE_SPECIFIER static inline
#define PJ_ATTR_NORETURN __attribute__ ((noreturn))
#define PJ_ATTR_MAY_ALIAS __attribute__((__may_alias__))
#endif
#define PJ_INT64(val) val##LL
#define PJ_UINT64(val) val##ULL
#define PJ_INT64_FMT "L"
#define PJ_UNREACHED(x)
#define PJ_ALIGN_DATA(declaration, alignment) declaration __attribute__((aligned(alignment)))
#endif /* __PJ_COMPAT_CC_CLANG_H__ */

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_CC_CODEW_H__
#define __PJ_COMPAT_CC_CODEW_H__
/**
* @file cc_codew.h
* @brief Describes MetroWerks Code Warrior compiler specifics.
*/
#ifndef __MWERKS__
# error "This file is only for Code Warrior!"
#endif
#define PJ_CC_NAME "codewarrior"
#define PJ_CC_VER_1 ((__MWERKS__ & 0xF000) >> 12)
#define PJ_CC_VER_2 ((__MWERKS__ & 0x0F00) >> 8)
#define PJ_CC_VER_3 ((__MWERKS__ & 0xFF))
#define PJ_INLINE_SPECIFIER static inline
#define PJ_THREAD_FUNC
#define PJ_NORETURN
#define PJ_ATTR_NORETURN
#define PJ_ATTR_MAY_ALIAS
#define PJ_HAS_INT64 1
typedef long long pj_int64_t;
typedef unsigned long long pj_uint64_t;
#define PJ_INT64(val) val##LL
#define PJ_UINT64(val) val##LLU
#define PJ_INT64_FMT "L"
#define PJ_UNREACHED(x)
#endif /* __PJ_COMPAT_CC_CODEW_H__ */

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_CC_GCC_H__
#define __PJ_COMPAT_CC_GCC_H__
/**
* @file cc_gcc.h
* @brief Describes GCC compiler specifics.
*/
#ifndef __GNUC__
# error "This file is only for gcc!"
#endif
#define PJ_CC_NAME "gcc"
#define PJ_CC_VER_1 __GNUC__
#define PJ_CC_VER_2 __GNUC_MINOR__
/* __GNUC_PATCHLEVEL__ doesn't exist in gcc-2.9x.x */
#ifdef __GNUC_PATCHLEVEL__
# define PJ_CC_VER_3 __GNUC_PATCHLEVEL__
#else
# define PJ_CC_VER_3 0
#endif
#define PJ_THREAD_FUNC
#define PJ_NORETURN
#define PJ_HAS_INT64 1
#ifdef __STRICT_ANSI__
#include <inttypes.h>
typedef int64_t pj_int64_t;
typedef uint64_t pj_uint64_t;
#define PJ_INLINE_SPECIFIER static __inline
#define PJ_ATTR_NORETURN
#define PJ_ATTR_MAY_ALIAS
#else
typedef long long pj_int64_t;
typedef unsigned long long pj_uint64_t;
#define PJ_INLINE_SPECIFIER static inline
#define PJ_ATTR_NORETURN __attribute__ ((noreturn))
#define PJ_ATTR_MAY_ALIAS __attribute__((__may_alias__))
#endif
#define PJ_INT64(val) val##LL
#define PJ_UINT64(val) val##ULL
#define PJ_INT64_FMT "L"
#ifdef __GLIBC__
# define PJ_HAS_BZERO 1
#endif
#define PJ_UNREACHED(x)
#define PJ_ALIGN_DATA(declaration, alignment) declaration __attribute__((aligned (alignment)))
#endif /* __PJ_COMPAT_CC_GCC_H__ */

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_CC_GCCE_H__
#define __PJ_COMPAT_CC_GCCE_H__
/**
* @file cc_gcce.h
* @brief Describes GCCE compiler specifics.
*/
#ifndef __GCCE__
# error "This file is only for gcce!"
#endif
#define PJ_CC_NAME "gcce"
#define PJ_CC_VER_1 __GCCE__
#define PJ_CC_VER_2 __GCCE_MINOR__
#define PJ_CC_VER_3 __GCCE_PATCHLEVEL__
#define PJ_INLINE_SPECIFIER static inline
#define PJ_THREAD_FUNC
#define PJ_NORETURN
#define PJ_ATTR_NORETURN __attribute__ ((noreturn))
#define PJ_ATTR_MAY_ALIAS __attribute__ ((__may_alias__))
#define PJ_HAS_INT64 1
typedef long long pj_int64_t;
typedef unsigned long long pj_uint64_t;
#define PJ_INT64(val) val##LL
#define PJ_UINT64(val) val##LLU
#define PJ_INT64_FMT "L"
#endif /* __PJ_COMPAT_CC_GCCE_H__ */

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_CC_MSVC_H__
#define __PJ_COMPAT_CC_MSVC_H__
/**
* @file cc_msvc.h
* @brief Describes Microsoft Visual C compiler specifics.
*/
#ifndef _MSC_VER
# error "This header file is only for Visual C compiler!"
#endif
#define PJ_CC_NAME "msvc"
#define PJ_CC_VER_1 (_MSC_VER/100)
#define PJ_CC_VER_2 (_MSC_VER%100)
#define PJ_CC_VER_3 0
/* Disable CRT deprecation warnings. */
#if PJ_CC_VER_1 >= 8 && !defined(_CRT_SECURE_NO_DEPRECATE)
# define _CRT_SECURE_NO_DEPRECATE
#endif
#if PJ_CC_VER_1 >= 8 && !defined(_CRT_SECURE_NO_WARNINGS)
# define _CRT_SECURE_NO_WARNINGS
/* The above doesn't seem to work, at least on VS2005, so lets use
* this construct as well.
*/
# pragma warning(disable: 4996)
#endif
#pragma warning(disable: 4127) // conditional expression is constant
#pragma warning(disable: 4611) // not wise to mix setjmp with C++
#pragma warning(disable: 4514) // unref. inline function has been removed
#ifdef NDEBUG
# pragma warning(disable: 4702) // unreachable code
# pragma warning(disable: 4710) // function is not inlined.
# pragma warning(disable: 4711) // function selected for auto inline expansion
#endif
#ifdef __cplusplus
# define PJ_INLINE_SPECIFIER inline
#else
# define PJ_INLINE_SPECIFIER static __inline
#endif
#define PJ_EXPORT_DECL_SPECIFIER __declspec(dllexport)
#define PJ_EXPORT_DEF_SPECIFIER __declspec(dllexport)
#define PJ_IMPORT_DECL_SPECIFIER __declspec(dllimport)
#define PJ_THREAD_FUNC
#define PJ_NORETURN __declspec(noreturn)
#define PJ_ATTR_NORETURN
#define PJ_ATTR_MAY_ALIAS
#define PJ_HAS_INT64 1
typedef __int64 pj_int64_t;
typedef unsigned __int64 pj_uint64_t;
#define PJ_INT64(val) val##i64
#define PJ_UINT64(val) val##ui64
#define PJ_INT64_FMT "I64"
#define PJ_UNREACHED(x)
#define PJ_ALIGN_DATA(declaration, alignment) __declspec(align(alignment)) declaration
#endif /* __PJ_COMPAT_CC_MSVC_H__ */

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_CC_MWCC_H__
#define __PJ_COMPAT_CC_MWCC_H__
/**
* @file cc_mwcc.h
* @brief Describes MWCC compiler specifics.
*/
#ifndef __CW32__
# error "This file is only for mwcc!"
#endif
#define PJ_CC_NAME "mwcc32sym"
#define PJ_CC_VER_1 1
#define PJ_CC_VER_2 0
#define PJ_CC_VER_3 0
#define PJ_INLINE_SPECIFIER static inline
#define PJ_THREAD_FUNC
#define PJ_NORETURN
#define PJ_ATTR_NORETURN __attribute__ ((noreturn))
#define PJ_ATTR_MAY_ALIAS
#define PJ_HAS_INT64 1
typedef long long pj_int64_t;
typedef unsigned long long pj_uint64_t;
#define PJ_INT64(val) val##LL
#define PJ_UINT64(val) val##LLU
#define PJ_INT64_FMT "L"
#define PJ_UNREACHED(x)
#endif /* __PJ_COMPAT_CC_MWCC_H__ */

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_CTYPE_H__
#define __PJ_COMPAT_CTYPE_H__
/**
* @file ctype.h
* @brief Provides ctype function family.
*/
#if defined(PJ_HAS_CTYPE_H) && PJ_HAS_CTYPE_H != 0
# include <ctype.h>
#else
# define isalnum(c) (isalpha(c) || isdigit(c))
# define isalpha(c) (islower(c) || isupper(c))
# define isascii(c) (((unsigned char)(c))<=0x7f)
# define isdigit(c) ((c)>='0' && (c)<='9')
# define isspace(c) ((c)==' ' || (c)=='\t' ||\
(c)=='\n' || (c)=='\r' || (c)=='\v')
# define islower(c) ((c)>='a' && (c)<='z')
# define isupper(c) ((c)>='A' && (c)<='Z')
# define isxdigit(c) (isdigit(c) || (tolower(c)>='a'&&tolower(c)<='f'))
# define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)+('a'-'A') : (c))
# define toupper(c) (((c) >= 'a' && (c) <= 'z') ? (c)-('a'-'A') : (c))
#endif
#endif /* __PJ_COMPAT_CTYPE_H__ */

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_ERRNO_H__
#define __PJ_COMPAT_ERRNO_H__
#if defined(PJ_WIN32) && PJ_WIN32 != 0 || \
defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE != 0 || \
defined(PJ_WIN64) && PJ_WIN64 != 0
typedef unsigned long pj_os_err_type;
# define pj_get_native_os_error() GetLastError()
# define pj_get_native_netos_error() WSAGetLastError()
#elif defined(PJ_HAS_ERRNO_VAR) && PJ_HAS_ERRNO_VAR!= 0
typedef int pj_os_err_type;
# define pj_get_native_os_error() (errno)
# define pj_get_native_netos_error() (errno)
#else
# error "Please define how to get errno for this platform here!"
#endif
#endif /* __PJ_COMPAT_ERRNO_H__ */

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_HIGH_PRECISION_H__
#define __PJ_COMPAT_HIGH_PRECISION_H__
#if defined(PJ_HAS_FLOATING_POINT) && PJ_HAS_FLOATING_POINT != 0
/*
* The first choice for high precision math is to use double.
*/
# include <math.h>
typedef double pj_highprec_t;
# define PJ_HIGHPREC_VALUE_IS_ZERO(a) (a==0)
# define pj_highprec_mod(a,b) (a=fmod(a,b))
#elif defined(PJ_HAS_INT64) && PJ_HAS_INT64 != 0
/*
* Next choice is to use 64-bit arithmatics.
*/
typedef pj_int64_t pj_highprec_t;
#else
# warning "High precision math is not available"
/*
* Last, fallback to 32-bit arithmetics.
*/
typedef pj_int32_t pj_highprec_t;
#endif
/**
* @def pj_highprec_mul
* pj_highprec_mul(a1, a2) - High Precision Multiplication
* Multiply a1 and a2, and store the result in a1.
*/
#ifndef pj_highprec_mul
# define pj_highprec_mul(a1,a2) (a1 = a1 * a2)
#endif
/**
* @def pj_highprec_div
* pj_highprec_div(a1, a2) - High Precision Division
* Divide a2 from a1, and store the result in a1.
*/
#ifndef pj_highprec_div
# define pj_highprec_div(a1,a2) (a1 = a1 / a2)
#endif
/**
* @def pj_highprec_mod
* pj_highprec_mod(a1, a2) - High Precision Modulus
* Get the modulus a2 from a1, and store the result in a1.
*/
#ifndef pj_highprec_mod
# define pj_highprec_mod(a1,a2) (a1 = a1 % a2)
#endif
/**
* @def PJ_HIGHPREC_VALUE_IS_ZERO(a)
* Test if the specified high precision value is zero.
*/
#ifndef PJ_HIGHPREC_VALUE_IS_ZERO
# define PJ_HIGHPREC_VALUE_IS_ZERO(a) (a==0)
#endif
#endif /* __PJ_COMPAT_HIGH_PRECISION_H__ */

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2017 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2017 George Joseph <gjoseph@digium.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_LIMITS_H__
#define __PJ_COMPAT_LIMITS_H__
/**
* @file limits.h
* @brief Provides integer limits normally found in limits.h.
*/
#include <pj/config.h>
#if defined(PJ_HAS_LIMITS_H) && PJ_HAS_LIMITS_H != 0
# include <limits.h>
#else
# ifdef _MSC_VER
# pragma message("limits.h is not found or not supported. LONG_MIN and "\
"LONG_MAX will be defined by the library in "\
"pj/compats/limits.h and overridable in config_site.h")
# else
# warning "limits.h is not found or not supported. LONG_MIN and LONG_MAX " \
"will be defined by the library in pj/compats/limits.h and "\
"overridable in config_site.h"
# endif
/* Minimum and maximum values a `signed long int' can hold. */
# ifndef LONG_MAX
# if __WORDSIZE == 64
# define LONG_MAX 9223372036854775807L
# else
# define LONG_MAX 2147483647L
# endif
# endif
# ifndef LONG_MIN
# define LONG_MIN (-LONG_MAX - 1L)
# endif
/* Maximum value an `unsigned long int' can hold. (Minimum is 0.) */
# ifndef ULONG_MAX
# if __WORDSIZE == 64
# define ULONG_MAX 18446744073709551615UL
# else
# define ULONG_MAX 4294967295UL
# endif
# endif
#endif
#endif /* __PJ_COMPAT_LIMITS_H__ */

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_M_ALPHA_H__
#define __PJ_COMPAT_M_ALPHA_H__
/**
* @file m_alpha.h
* @brief Describes Alpha processor family specifics.
*/
#define PJ_M_NAME "alpha"
#define PJ_HAS_PENTIUM 0
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
#endif /* __PJ_COMPAT_M_ALPHA_H__ */

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_M_ARMV4_H__
#define __PJ_COMPAT_M_ARMV4_H__
/**
* @file m_armv4.h
* @brief Describes ARM family processor specifics.
*/
/*
* This file covers PJ_M_ARMV4 etc.
*/
#define PJ_M_NAME "armv4"
#define PJ_HAS_PENTIUM 0
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
#endif /* __PJ_COMPAT_M_ARMV4_H__ */

View File

@@ -0,0 +1,60 @@
/* pjlib/include/pj/compat/m_auto.h. Generated from m_auto.h.in by configure. */
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_M_AUTO_H__
#define __PJ_COMPAT_M_AUTO_H__
/**
* @file m_auto.h
* @brief Automatically generated process definition file.
*/
/* Machine name, filled in by autoconf script */
#define PJ_M_NAME "aarch64"
/* Endianness. It's reported on pjsip list on 09/02/13 that autoconf
* endianness detection failed for universal build, so special case
* for it here. Thanks Ruud Klaver for the fix.
*/
#ifdef PJ_DARWINOS
# ifdef __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
/* Endianness, as detected by autoconf */
/* # undef WORDS_BIGENDIAN */
#endif
#ifdef WORDS_BIGENDIAN
# define PJ_IS_LITTLE_ENDIAN 0
# define PJ_IS_BIG_ENDIAN 1
#else
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
#endif
/* Specify if floating point is present/desired */
#define PJ_HAS_FLOATING_POINT 1
/* Deprecated */
#define PJ_HAS_PENTIUM 0
#endif /* __PJ_COMPAT_M_AUTO_H__ */

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_M_AUTO_H__
#define __PJ_COMPAT_M_AUTO_H__
/**
* @file m_auto.h
* @brief Automatically generated process definition file.
*/
/* Machine name, filled in by autoconf script */
#undef PJ_M_NAME
/* Endianness. It's reported on pjsip list on 09/02/13 that autoconf
* endianness detection failed for universal build, so special case
* for it here. Thanks Ruud Klaver for the fix.
*/
#ifdef PJ_DARWINOS
# ifdef __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
/* Endianness, as detected by autoconf */
# undef WORDS_BIGENDIAN
#endif
#ifdef WORDS_BIGENDIAN
# define PJ_IS_LITTLE_ENDIAN 0
# define PJ_IS_BIG_ENDIAN 1
#else
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
#endif
/* Specify if floating point is present/desired */
#undef PJ_HAS_FLOATING_POINT
/* Deprecated */
#define PJ_HAS_PENTIUM 0
#endif /* __PJ_COMPAT_M_AUTO_H__ */

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_M_i386_H__
#define __PJ_COMPAT_M_i386_H__
/**
* @file m_i386.h
* @brief Describes Intel i386 family processor specifics.
*/
#define PJ_M_NAME "i386"
#define PJ_HAS_PENTIUM 1
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
#endif /* __PJ_COMPAT_M_i386_H__ */

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_M_M68K_H__
#define __PJ_COMPAT_M_M68K_H__
/**
* @file m_m68k.h
* @brief Describes Motorola m68k family processor specifics.
*/
#define PJ_M_NAME "m68k"
#define PJ_HAS_PENTIUM 0
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
#endif /* __PJ_COMPAT_M_M68K_H__ */

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_M_POWERPC_H__
#define __PJ_COMPAT_M_POWERPC_H__
/**
* @file m_ppc.h
* @brief Describes PowerPC family processor specifics.
*/
#define PJ_M_NAME "powerpc"
#define PJ_HAS_PENTIUM 0
#define PJ_IS_LITTLE_ENDIAN 0
#define PJ_IS_BIG_ENDIAN 1
#endif /* __PJ_COMPAT_M_POWERPC_H__ */

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_M_SPARC_H__
#define __PJ_COMPAT_M_SPARC_H__
/**
* @file m_sparc.h
* @brief Describes SPARC family processor specifics.
*/
#define PJ_M_NAME "sparc"
#define PJ_HAS_PENTIUM 0
#define PJ_IS_LITTLE_ENDIAN 0
#define PJ_IS_BIG_ENDIAN 1
#endif /* __PJ_COMPAT_M_SPARC_H__ */

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_M_x86_64_H__
#define __PJ_COMPAT_M_x86_64_H__
/**
* @file m_i386.h
* @brief Describes 64bit x86 Intel/AMD family processor specifics.
*/
#define PJ_M_NAME "x86_64"
#define PJ_HAS_PENTIUM 1
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
#endif /* __PJ_COMPAT_M_x86_64_H__ */

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_MALLOC_H__
#define __PJ_COMPAT_MALLOC_H__
/**
* @file malloc.h
* @brief Provides malloc() and free() functions.
*/
#if defined(PJ_HAS_MALLOC_H) && PJ_HAS_MALLOC_H != 0
# include <malloc.h>
#elif defined(PJ_HAS_STDLIB_H) && PJ_HAS_STDLIB_H != 0
# include <stdlib.h>
#endif
#endif /* __PJ_COMPAT_MALLOC_H__ */

View File

@@ -0,0 +1,245 @@
/* pjlib/include/pj/compat/os_auto.h. Generated from os_auto.h.in by configure. */
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_AUTO_H__
#define __PJ_COMPAT_OS_AUTO_H__
/**
* @file os_auto.h
* @brief Describes operating system specifics (automatically detected by
* autoconf)
*/
/* Canonical OS name */
#define PJ_OS_NAME "aarch64-unknown-linux-android"
/* Legacy macros */
/* #undef PJ_WIN64 */
/* #undef PJ_WIN32 */
/* #undef PJ_WIN32_WINNT */
/* #undef WIN32_LEAN_AND_MEAN */
/* #undef PJ_DARWINOS */
/* #undef PJ_LINUX */
/* #undef PJ_BSD */
/* #undef PJ_RTEMS */
/* #undef PJ_SUNOS */
#define PJ_ANDROID 1
#if defined(PJ_WIN32_WINNT) && !defined(_WIN32_WINNT)
# define _WIN32_WINNT PJ_WIN32_WINNT
#endif
/* Headers availability */
#define PJ_HAS_ARPA_INET_H 1
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 1
#define PJ_HAS_FCNTL_H 1
#define PJ_HAS_LIMITS_H 1
#define PJ_HAS_LINUX_SOCKET_H 1
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 1
#define PJ_HAS_NETINET_IN_SYSTM_H 1
#define PJ_HAS_NETINET_IN_H 1
#define PJ_HAS_NETINET_IP_H 1
#define PJ_HAS_NETINET_TCP_H 1
#define PJ_HAS_NET_IF_H 1
#define PJ_HAS_IFADDRS_H 1
#define PJ_HAS_INTTYPES_H 1
#define PJ_HAS_SEMAPHORE_H 1
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDINT_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 1
#define PJ_HAS_SYS_SELECT_H 1
#define PJ_HAS_SYS_SOCKET_H 1
#define PJ_HAS_SYS_TIME_H 1
/* #undef PJ_HAS_SYS_TIMEB_H */
#define PJ_HAS_SYS_TYPES_H 1
/* #undef PJ_HAS_SYS_FILIO_H */
/* #undef PJ_HAS_SYS_SOCKIO_H */
#define PJ_HAS_SYS_UTSNAME_H 1
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 1
#define PJ_HAS_EXECINFO_H 1
/* #undef PJ_HAS_MSWSOCK_H */
/* #undef PJ_HAS_WINSOCK_H */
/* #undef PJ_HAS_WINSOCK2_H */
/* #undef PJ_HAS_WS2TCPIP_H */
#define PJ_SOCK_HAS_IPV6_V6ONLY 1
#define PJ_SOCK_HAS_INET_ATON 1
#define PJ_SOCK_HAS_INET_PTON 1
#define PJ_SOCK_HAS_INET_NTOP 1
#define PJ_SOCK_HAS_GETADDRINFO 1
#define PJ_SOCK_HAS_SOCKETPAIR 1
/* On these OSes, semaphore feature depends on semaphore.h */
#if defined(PJ_HAS_SEMAPHORE_H) && PJ_HAS_SEMAPHORE_H!=0
# define PJ_HAS_SEMAPHORE 1
#elif defined(PJ_WIN32) && PJ_WIN32!=0
# define PJ_HAS_SEMAPHORE 1
#else
# define PJ_HAS_SEMAPHORE 0
#endif
/* Do we have pthread_mutexattr_settype()? */
/* #undef PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE */
/* Does pthread_mutexattr_t has "recursive" member? */
/* #undef PJ_PTHREAD_MUTEXATTR_T_HAS_RECURSIVE */
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
/* #undef PJ_SOCKADDR_HAS_LEN */
/* Does the OS have socklen_t? */
#define PJ_HAS_SOCKLEN_T 1
#if !defined(socklen_t) && (!defined(PJ_HAS_SOCKLEN_T) || PJ_HAS_SOCKLEN_T==0)
# define PJ_HAS_SOCKLEN_T 1
typedef int socklen_t;
#endif
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* Was Linux epoll support enabled */
/* #undef PJ_HAS_LINUX_EPOLL */
/* Is errno a good way to retrieve OS errors?
*/
#define PJ_HAS_ERRNO_VAR 1
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 1
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() can not return immediate daata.
*/
#define PJ_BLOCKING_ERROR_VAL EAGAIN
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL EINPROGRESS
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
/* Do we need high resolution timer? */
#define PJ_HAS_HIGH_RES_TIMER 1
/* Is malloc() available? */
#define PJ_HAS_MALLOC 1
#ifndef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
#endif
/* Is localtime_r() available? */
#define PJ_HAS_LOCALTIME_R 1
/* Unicode? */
#define PJ_NATIVE_STRING_IS_UNICODE 0
/* Pool alignment in bytes */
#define PJ_POOL_ALIGNMENT 8
/* The type of atomic variable value: */
#define PJ_ATOMIC_VALUE_TYPE long
#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
/* Disable local host resolution in pj_gethostip() (see ticket #1342) */
# define PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION 1
/* Use pj_getaddrinfo() (instead of pj_inet_pton()) in
* pj_sockaddr_set_str_addr()
*/
# define PJ_SOCKADDR_USE_GETADDRINFO 1
# include "TargetConditionals.h"
# if TARGET_OS_IPHONE
# include "Availability.h"
/* Use CFHost API for pj_getaddrinfo() (see ticket #1246) */
# ifndef PJ_GETADDRINFO_USE_CFHOST
# define PJ_GETADDRINFO_USE_CFHOST 0
# endif
# ifdef __IPHONE_4_0
/* Is multitasking support available? (see ticket #1107) */
# define PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT 1
/* Activesock TCP background mode support (VoIP socket).
* Disabled by default, VoIP socket deprecated since iOS 9 and
* on iOS16 using VoIP socket causes app getting killed.
*/
# define PJ_ACTIVESOCK_TCP_IPHONE_OS_BG 0
# endif
# endif
#endif
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 0
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
/* SSL socket availability. */
#ifndef PJ_HAS_SSL_SOCK
/* #undef PJ_HAS_SSL_SOCK */
#endif
#ifndef PJ_SSL_SOCK_IMP
/* #undef PJ_SSL_SOCK_IMP */
#endif
/* Has pthread_np.h ? */
/* #undef PJ_HAS_PTHREAD_NP_H */
/* Has pthread_setname_np() ? */
#define PJ_HAS_PTHREAD_SETNAME_NP 1
/* Has pthread_set_name_np() ? */
/* #undef PJ_HAS_PTHREAD_SET_NAME_NP */
#endif /* __PJ_COMPAT_OS_AUTO_H__ */

View File

@@ -0,0 +1,244 @@
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_AUTO_H__
#define __PJ_COMPAT_OS_AUTO_H__
/**
* @file os_auto.h
* @brief Describes operating system specifics (automatically detected by
* autoconf)
*/
/* Canonical OS name */
#undef PJ_OS_NAME
/* Legacy macros */
#undef PJ_WIN64
#undef PJ_WIN32
#undef PJ_WIN32_WINNT
#undef WIN32_LEAN_AND_MEAN
#undef PJ_DARWINOS
#undef PJ_LINUX
#undef PJ_BSD
#undef PJ_RTEMS
#undef PJ_SUNOS
#undef PJ_ANDROID
#if defined(PJ_WIN32_WINNT) && !defined(_WIN32_WINNT)
# define _WIN32_WINNT PJ_WIN32_WINNT
#endif
/* Headers availability */
#undef PJ_HAS_ARPA_INET_H
#undef PJ_HAS_ASSERT_H
#undef PJ_HAS_CTYPE_H
#undef PJ_HAS_ERRNO_H
#undef PJ_HAS_FCNTL_H
#undef PJ_HAS_LIMITS_H
#undef PJ_HAS_LINUX_SOCKET_H
#undef PJ_HAS_MALLOC_H
#undef PJ_HAS_NETDB_H
#undef PJ_HAS_NETINET_IN_SYSTM_H
#undef PJ_HAS_NETINET_IN_H
#undef PJ_HAS_NETINET_IP_H
#undef PJ_HAS_NETINET_TCP_H
#undef PJ_HAS_NET_IF_H
#undef PJ_HAS_IFADDRS_H
#undef PJ_HAS_INTTYPES_H
#undef PJ_HAS_SEMAPHORE_H
#undef PJ_HAS_SETJMP_H
#undef PJ_HAS_STDARG_H
#undef PJ_HAS_STDDEF_H
#undef PJ_HAS_STDIO_H
#undef PJ_HAS_STDINT_H
#undef PJ_HAS_STDLIB_H
#undef PJ_HAS_STRING_H
#undef PJ_HAS_SYS_IOCTL_H
#undef PJ_HAS_SYS_SELECT_H
#undef PJ_HAS_SYS_SOCKET_H
#undef PJ_HAS_SYS_TIME_H
#undef PJ_HAS_SYS_TIMEB_H
#undef PJ_HAS_SYS_TYPES_H
#undef PJ_HAS_SYS_FILIO_H
#undef PJ_HAS_SYS_SOCKIO_H
#undef PJ_HAS_SYS_UTSNAME_H
#undef PJ_HAS_TIME_H
#undef PJ_HAS_UNISTD_H
#undef PJ_HAS_EXECINFO_H
#undef PJ_HAS_MSWSOCK_H
#undef PJ_HAS_WINSOCK_H
#undef PJ_HAS_WINSOCK2_H
#undef PJ_HAS_WS2TCPIP_H
#undef PJ_SOCK_HAS_IPV6_V6ONLY
#undef PJ_SOCK_HAS_INET_ATON
#undef PJ_SOCK_HAS_INET_PTON
#undef PJ_SOCK_HAS_INET_NTOP
#undef PJ_SOCK_HAS_GETADDRINFO
#undef PJ_SOCK_HAS_SOCKETPAIR
/* On these OSes, semaphore feature depends on semaphore.h */
#if defined(PJ_HAS_SEMAPHORE_H) && PJ_HAS_SEMAPHORE_H!=0
# define PJ_HAS_SEMAPHORE 1
#elif defined(PJ_WIN32) && PJ_WIN32!=0
# define PJ_HAS_SEMAPHORE 1
#else
# define PJ_HAS_SEMAPHORE 0
#endif
/* Do we have pthread_mutexattr_settype()? */
#undef PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE
/* Does pthread_mutexattr_t has "recursive" member? */
#undef PJ_PTHREAD_MUTEXATTR_T_HAS_RECURSIVE
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#undef PJ_SOCKADDR_HAS_LEN
/* Does the OS have socklen_t? */
#undef PJ_HAS_SOCKLEN_T
#if !defined(socklen_t) && (!defined(PJ_HAS_SOCKLEN_T) || PJ_HAS_SOCKLEN_T==0)
# define PJ_HAS_SOCKLEN_T 1
typedef int socklen_t;
#endif
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#undef PJ_SELECT_NEEDS_NFDS
/* Was Linux epoll support enabled */
#undef PJ_HAS_LINUX_EPOLL
/* Is errno a good way to retrieve OS errors?
*/
#undef PJ_HAS_ERRNO_VAR
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#undef PJ_HAS_SO_ERROR
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() can not return immediate daata.
*/
#undef PJ_BLOCKING_ERROR_VAL
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#undef PJ_BLOCKING_CONNECT_ERROR_VAL
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
/* Do we need high resolution timer? */
#undef PJ_HAS_HIGH_RES_TIMER
/* Is malloc() available? */
#undef PJ_HAS_MALLOC
#ifndef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
#endif
/* Is localtime_r() available? */
#undef PJ_HAS_LOCALTIME_R
/* Unicode? */
#undef PJ_NATIVE_STRING_IS_UNICODE
/* Pool alignment in bytes */
#undef PJ_POOL_ALIGNMENT
/* The type of atomic variable value: */
#undef PJ_ATOMIC_VALUE_TYPE
#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
/* Disable local host resolution in pj_gethostip() (see ticket #1342) */
# define PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION 1
/* Use pj_getaddrinfo() (instead of pj_inet_pton()) in
* pj_sockaddr_set_str_addr()
*/
# define PJ_SOCKADDR_USE_GETADDRINFO 1
# include "TargetConditionals.h"
# if TARGET_OS_IPHONE
# include "Availability.h"
/* Use CFHost API for pj_getaddrinfo() (see ticket #1246) */
# ifndef PJ_GETADDRINFO_USE_CFHOST
# define PJ_GETADDRINFO_USE_CFHOST 0
# endif
# ifdef __IPHONE_4_0
/* Is multitasking support available? (see ticket #1107) */
# define PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT 1
/* Activesock TCP background mode support (VoIP socket).
* Disabled by default, VoIP socket deprecated since iOS 9 and
* on iOS16 using VoIP socket causes app getting killed.
*/
# define PJ_ACTIVESOCK_TCP_IPHONE_OS_BG 0
# endif
# endif
#endif
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#undef PJ_EMULATE_RWMUTEX
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#undef PJ_THREAD_SET_STACK_SIZE
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#undef PJ_THREAD_ALLOCATE_STACK
/* SSL socket availability. */
#ifndef PJ_HAS_SSL_SOCK
#undef PJ_HAS_SSL_SOCK
#endif
#ifndef PJ_SSL_SOCK_IMP
#undef PJ_SSL_SOCK_IMP
#endif
/* Has pthread_np.h ? */
#undef PJ_HAS_PTHREAD_NP_H
/* Has pthread_setname_np() ? */
#undef PJ_HAS_PTHREAD_SETNAME_NP
/* Has pthread_set_name_np() ? */
#undef PJ_HAS_PTHREAD_SET_NAME_NP
#endif /* __PJ_COMPAT_OS_AUTO_H__ */

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_DARWINOS_H__
#define __PJ_COMPAT_OS_DARWINOS_H__
/**
* @file os_darwinos.h
* @brief Describes Darwin/MacOSX operating system specifics.
*/
#define PJ_OS_NAME "darwin"
#define PJ_HAS_ARPA_INET_H 1
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 1
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 0
#define PJ_HAS_NETDB_H 1
#define PJ_HAS_NETINET_IN_H 1
#define PJ_HAS_NETINET_TCP_H 1
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 1
#define PJ_HAS_SYS_SELECT_H 1
#define PJ_HAS_SYS_SOCKET_H 1
#define PJ_HAS_SYS_TIME_H 1
#define PJ_HAS_SYS_TIMEB_H 1
#define PJ_HAS_SYS_TYPES_H 1
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 1
#define PJ_HAS_MSWSOCK_H 0
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 0
#define PJ_HAS_LOCALTIME_R 1
/* Is errno a good way to retrieve OS errors?
*/
#define PJ_HAS_ERRNO_VAR 1
/* Has inet_aton() ?
*/
#define PJ_SOCK_HAS_INET_ATON 1
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 1
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() can not return immediate daata.
*/
#define PJ_BLOCKING_ERROR_VAL EWOULDBLOCK
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL EINPROGRESS
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
#define PJ_HAS_HIGH_RES_TIMER 1
#define PJ_HAS_MALLOC 1
#ifndef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
#endif
#define PJ_NATIVE_STRING_IS_UNICODE 0
#define PJ_ATOMIC_VALUE_TYPE long
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 1
/*
* gcc complains that it can not use precompiled header because
* the value of FD_SETSIZE that we declare in pj/config.h is
* different than the value in /usr/include/sys/types.h.
*
* This changes the default value for Darwin.
*/
#define PJ_IOQUEUE_MAX_HANDLES 1024
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 0
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
/* MacOS has had socklen since 10.4 */
#define PJ_HAS_SOCKLEN_T 1
#endif /* __PJ_COMPAT_OS_DARWINOS_H__ */

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_LINUX_H__
#define __PJ_COMPAT_OS_LINUX_H__
/**
* @file os_linux.h
* @brief Describes Linux operating system specifics.
*/
#define PJ_OS_NAME "linux"
#define PJ_HAS_ARPA_INET_H 1
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 1
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 1
#define PJ_HAS_NETINET_IN_H 1
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 1
#define PJ_HAS_SYS_SELECT_H 1
#define PJ_HAS_SYS_SOCKET_H 1
#define PJ_HAS_SYS_TIME_H 1
#define PJ_HAS_SYS_TIMEB_H 1
#define PJ_HAS_SYS_TYPES_H 1
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 1
#define PJ_HAS_SEMAPHORE_H 1
#define PJ_HAS_MSWSOCK_H 0
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 0
#define PJ_HAS_LOCALTIME_R 1
#define PJ_SOCK_HAS_INET_ATON 1
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 0
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* Is errno a good way to retrieve OS errors?
*/
#define PJ_HAS_ERRNO_VAR 1
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 1
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() can not return immediate daata.
*/
#define PJ_BLOCKING_ERROR_VAL EAGAIN
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL EINPROGRESS
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
#define PJ_HAS_HIGH_RES_TIMER 1
#define PJ_HAS_MALLOC 1
#ifndef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
#endif
#define PJ_NATIVE_STRING_IS_UNICODE 0
#define PJ_ATOMIC_VALUE_TYPE long
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 0
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
/* Linux has socklen_t */
#define PJ_HAS_SOCKLEN_T 1
#endif /* __PJ_COMPAT_OS_LINUX_H__ */

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_PALMOS_H__
#define __PJ_COMPAT_OS_PALMOS_H__
/**
* @file os_palmos.h
* @brief Describes PalmOS operating system specifics.
*/
#define PJ_OS_NAME "palmos"
#define PJ_HAS_ARPA_INET_H 0
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 0
#define PJ_HAS_NETINET_IN_H 0
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 0
#define PJ_HAS_SYS_SELECT_H 0
#define PJ_HAS_SYS_SOCKET_H 0
#define PJ_HAS_SYS_TIMEB_H 0
#define PJ_HAS_SYS_TYPES_H 1
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 0
#define PJ_HAS_MSWSOCK_H 0
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 0
#define PJ_SOCK_HAS_INET_ATON 0
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 0
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* Is errno a good way to retrieve OS errors?
*/
#define PJ_HAS_ERRNO_VAR 0
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 0
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() can not return immediate daata.
*/
#define PJ_BLOCKING_ERROR_VAL xxx
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL xxx
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
#define PJ_HAS_HIGH_RES_TIMER 1
#ifndef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
#define PJ_NATIVE_STRING_IS_UNICODE 0
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 1
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
#endif /* __PJ_COMPAT_OS_PALMOS_H__ */

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Thanks Zetron, Inc and Phil Torre <ptorre@zetron.com> for donating PJLIB
* port to RTEMS.
*/
#ifndef __PJ_COMPAT_OS_RTEMS_H__
#define __PJ_COMPAT_OS_RTEMS_H__
/**
* @file os_linux.h
* @brief Describes Linux operating system specifics.
*/
#define PJ_OS_NAME "rtems"
#define PJ_HAS_ARPA_INET_H 1
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 1
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 1
#define PJ_HAS_NETINET_IN_H 1
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 0
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 1
#define PJ_HAS_SYS_SELECT_H 1
#define PJ_HAS_SYS_SOCKET_H 1
#define PJ_HAS_SYS_TIME_H 1
#define PJ_HAS_SYS_TIMEB_H 1
#define PJ_HAS_SYS_TYPES_H 1
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 1
#define PJ_HAS_MSWSOCK_H 0
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 0
#define PJ_SOCK_HAS_INET_ATON 1
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 1
/* Is errno a good way to retrieve OS errors?
*/
#define PJ_HAS_ERRNO_VAR 1
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 1
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 1
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() can not return immediate daata.
*/
#define PJ_BLOCKING_ERROR_VAL EWOULDBLOCK
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL EINPROGRESS
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
#define PJ_HAS_HIGH_RES_TIMER 1
#define PJ_HAS_MALLOC 1
#ifndef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
#endif
#define PJ_NATIVE_STRING_IS_UNICODE 0
#define PJ_ATOMIC_VALUE_TYPE int
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 1
/* Missing socklen_t */
typedef int socklen_t;
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 1
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 1
/* RTEMS has socklen_t (does it? )*/
#define PJ_HAS_SOCKLEN_T 1
#endif /* __PJ_COMPAT_OS_RTEMS_H__ */

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_SUNOS_H__
#define __PJ_COMPAT_OS_SUNOS_H__
/**
* @file os_sunos.h
* @brief Describes SunOS/Solaris operating system specifics.
*/
#define PJ_OS_NAME "sunos"
#define PJ_HAS_ARPA_INET_H 1
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 1
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 1
#define PJ_HAS_NETINET_IN_H 1
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 1
#define PJ_HAS_SYS_SELECT_H 1
#define PJ_HAS_SYS_SOCKET_H 1
#define PJ_HAS_SYS_TIME_H 0
#define PJ_HAS_SYS_TIMEB_H 1
#define PJ_HAS_SYS_TYPES_H 1
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 1
#define PJ_HAS_MSWSOCK_H 0
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 0
#define PJ_SOCK_HAS_INET_ATON 0
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 0
/* Is errno a good way to retrieve OS errors?
*/
#define PJ_HAS_ERRNO_VAR 1
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 0
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() can not return immediate daata.
*/
#define PJ_BLOCKING_ERROR_VAL EWOULDBLOCK
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL EINPROGRESS
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
#define PJ_HAS_HIGH_RES_TIMER 1
#define PJ_HAS_MALLOC 1
#ifndef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
#endif
#define PJ_NATIVE_STRING_IS_UNICODE 0
#define PJ_ATOMIC_VALUE_TYPE long
/* Get BSD related identifers in Sun's include files */
#define BSD_COMP
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 0
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
/* SunOS has socklen_t (does it? )*/
#define PJ_HAS_SOCKLEN_T 1
#endif /* __PJ_COMPAT_OS_SUNOS_H__ */

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_SYMBIAN_H__
#define __PJ_COMPAT_OS_SYMBIAN_H__
/**
* @file os_symbian.h
* @brief Describes Symbian operating system specifics.
*/
#define PJ_OS_NAME "symbian"
#define PJ_HAS_ARPA_INET_H 1
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 1
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 0
#define PJ_HAS_NETDB_H 1
#define PJ_HAS_NETINET_IN_H 1
#define PJ_HAS_NETINET_TCP_H 0
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_NO_SNPRINTF 1
#define PJ_HAS_SYS_IOCTL_H 1
#define PJ_HAS_SYS_SELECT_H 0
#define PJ_HAS_SYS_SOCKET_H 1
#define PJ_HAS_SYS_TIME_H 1
#define PJ_HAS_SYS_TIMEB_H 0
#define PJ_HAS_SYS_TYPES_H 1
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 1
#define PJ_HAS_MSWSOCK_H 0
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 0
#define PJ_SOCK_HAS_INET_ATON 0
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 0
/* Is errno a good way to retrieve OS errors?
*/
#define PJ_HAS_ERRNO_VAR 1
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 1
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() can not return immediate daata.
*/
#define PJ_BLOCKING_ERROR_VAL EAGAIN
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL EINPROGRESS
/*
* We don't want to use threads in Symbian
*/
#define PJ_HAS_THREADS 0
/*
* Declare __FD_SETSIZE now before including <linux*>.
#define __FD_SETSIZE PJ_IOQUEUE_MAX_HANDLES
*/
#ifndef NULL
# define NULL 0
#endif
/* Endianness */
#ifndef PJ_IS_LITTLE_ENDIAN
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
#endif
/* Doesn't seem to allow more than this */
#define PJ_IOQUEUE_MAX_HANDLES 8
/*
* Override features.
*/
#define PJ_HAS_FLOATING_POINT 0
#define PJ_HAS_MALLOC 0
#define PJ_HAS_SEMAPHORE 1
#define PJ_HAS_EVENT_OBJ 0
#define PJ_HAS_HIGH_RES_TIMER 1
#define PJ_OS_HAS_CHECK_STACK 0
#define PJ_TERM_HAS_COLOR 0
#define PJ_NATIVE_STRING_IS_UNICODE 0
#define PJ_NATIVE_ERR_POSITIVE 0
#define PJ_ATOMIC_VALUE_TYPE int
#define PJ_THREAD_DESC_SIZE 128
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 1
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
/* Missing socklen_t */
#define PJ_HAS_SOCKLEN_T 1
typedef unsigned int socklen_t;
#ifndef __GCCE__
#include <e32def.h>
#endif
#define PJ_EXPORT_DECL_SPECIFIER IMPORT_C
//#define PJ_EXPORT_DECL_SPECIFIER
#define PJ_EXPORT_DEF_SPECIFIER EXPORT_C
#define PJ_IMPORT_DECL_SPECIFIER IMPORT_C
#endif /* __PJ_COMPAT_OS_SYMBIAN_H__ */

View File

@@ -0,0 +1,148 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_WIN32_H__
#define __PJ_COMPAT_OS_WIN32_H__
/**
* @file os_win32.h
* @brief Describes Win32 operating system family specifics.
*/
#define PJ_OS_NAME "win32"
#define WIN32_LEAN_AND_MEAN
#define PJ_WIN32_WINNT 0x0501
#ifndef _WIN32_WINNT
# define _WIN32_WINNT PJ_WIN32_WINNT
#endif
#define PJ_HAS_ARPA_INET_H 0
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 0 /* Must be zero, otherwise errno_test() fails. */
#define PJ_HAS_INTTYPES_H 1
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 0
#define PJ_HAS_NETINET_IN_H 0
#define PJ_HAS_NETINET_TCP_H 0
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#undef PJ_HAS_STDINT_H
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 0
#define PJ_HAS_SYS_SELECT_H 0
#define PJ_HAS_SYS_SOCKET_H 0
#define PJ_HAS_SYS_TIME_H 0
#define PJ_HAS_SYS_TIMEB_H 1
#define PJ_HAS_SYS_TYPES_H 1
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 0
#define PJ_HAS_LIMITS_H 1
#define PJ_HAS_MSWSOCK_H 1
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 1
#define PJ_HAS_WS2TCPIP_H 1
#define PJ_SOCK_HAS_INET_ATON 0
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 0
/* Is errno a good way to retrieve OS errors? (No)
*/
#define PJ_HAS_ERRNO_VAR 0
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 1
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() or send() can not return immediately.
*/
#define PJ_BLOCKING_ERROR_VAL WSAEWOULDBLOCK
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL WSAEWOULDBLOCK
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
#define PJ_HAS_HIGH_RES_TIMER 1
#define PJ_HAS_MALLOC 1
#ifndef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 1
#endif
#ifdef UNICODE
# define PJ_NATIVE_STRING_IS_UNICODE 1
#else
# define PJ_NATIVE_STRING_IS_UNICODE 0
#endif
#define PJ_ATOMIC_VALUE_TYPE long
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 1
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
/* Endianness */
#if defined(_M_ARM64)
# ifndef PJ_IS_LITTLE_ENDIAN
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
# endif
#endif
#endif /* __PJ_COMPAT_OS_WIN32_H__ */

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_WIN32_WINCE_H__
#define __PJ_COMPAT_OS_WIN32_WINCE_H__
/**
* @file os_win32.h
* @brief Describes Win32 operating system family specifics.
*/
#define PJ_OS_NAME "win32-wince"
#define WIN32_LEAN_AND_MEAN
#define RPC_NO_WINDOWS_H
//#define PJ_WIN32_WINNT 0x0400
//#define _WIN32_WINNT PJ_WIN32_WINNT
#define PJ_HAS_ARPA_INET_H 0
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 0 /* Must be zero, otherwise errno_test() fails. */
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 0
#define PJ_HAS_NETINET_IN_H 0
#define PJ_HAS_NETINET_TCP_H 0
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 0
#define PJ_HAS_SYS_SELECT_H 0
#define PJ_HAS_SYS_SOCKET_H 0
#define PJ_HAS_SYS_TIME_H 0
#define PJ_HAS_SYS_TIMEB_H 0 /* Doesn't have sys/timeb.h */
#define PJ_HAS_SYS_TYPES_H 0 /* Doesn't have sys/types.h */
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 0
#define PJ_HAS_MSWSOCK_H 1
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 1
#define PJ_SOCK_HAS_INET_ATON 0
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 0
/* Is errno a good way to retrieve OS errors? (no)
*/
#define PJ_HAS_ERRNO_VAR 0
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 0
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() or send() can not return immediately.
*/
#define PJ_BLOCKING_ERROR_VAL WSAEWOULDBLOCK
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL WSAEWOULDBLOCK
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* Endianness */
#ifndef PJ_IS_LITTLE_ENDIAN
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
#endif
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
#define PJ_HAS_HIGH_RES_TIMER 1
#define PJ_HAS_MALLOC 1
#define PJ_OS_HAS_CHECK_STACK 1
#define PJ_ATOMIC_VALUE_TYPE long
/* TlsAlloc() error value. */
#define TLS_OUT_OF_INDEXES 0xFFFFFFFF
/* No console. */
#define PJ_TERM_HAS_COLOR 0
/* No rdtsc */
#define PJ_TIMESTAMP_USE_RDTSC 0
/* Native string is Unicode. */
#define PJ_NATIVE_STRING_IS_UNICODE 1
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 1
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
#endif /* __PJ_COMPAT_OS_WIN32_WINCE_H__ */

View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_WINPHONE8_H__
#define __PJ_COMPAT_OS_WINPHONE8_H__
/**
* @file os_winphone8.h
* @brief Describes Windows Phone 8 operating system family specifics.
*/
#define PJ_OS_NAME "winphone8"
#define WIN32_LEAN_AND_MEAN
#define RPC_NO_WINDOWS_H
#define PJ_WIN32_WINNT 0x0602 /*_WIN32_WINNT_WIN8*/
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#define _WIN32_WINNT PJ_WIN32_WINNT
#endif
#define PJ_HAS_ARPA_INET_H 0
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 0 /* Must be zero, otherwise errno_test() fails. */
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 0
#define PJ_HAS_NETINET_IN_H 0
#define PJ_HAS_NETINET_TCP_H 0
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 0
#define PJ_HAS_SYS_SELECT_H 0
#define PJ_HAS_SYS_SOCKET_H 0
#define PJ_HAS_SYS_TIME_H 0
#define PJ_HAS_SYS_TIMEB_H 0 /* Doesn't have sys/timeb.h */
#define PJ_HAS_SYS_TYPES_H 0 /* Doesn't have sys/types.h */
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 0
#define PJ_HAS_MSWSOCK_H 1
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 1
#define PJ_SOCK_HAS_INET_ATON 0
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 0
/* Is errno a good way to retrieve OS errors? (no)
*/
#define PJ_HAS_ERRNO_VAR 0
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 0
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() or send() can not return immediately.
*/
#define PJ_BLOCKING_ERROR_VAL WSAEWOULDBLOCK
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL WSAEWOULDBLOCK
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* Endianness */
#ifndef PJ_IS_LITTLE_ENDIAN
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
#endif
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
#define PJ_HAS_HIGH_RES_TIMER 1
#define PJ_HAS_MALLOC 1
#define PJ_OS_HAS_CHECK_STACK 1
#define PJ_ATOMIC_VALUE_TYPE long
/* No console. */
#define PJ_TERM_HAS_COLOR 0
/* TlsAlloc() error value. */
#ifndef TLS_OUT_OF_INDEXES
#define TLS_OUT_OF_INDEXES 0xFFFFFFFF
#endif
/* No rdtsc */
#define PJ_TIMESTAMP_USE_RDTSC 0
/* Native string is Unicode. */
#define PJ_NATIVE_STRING_IS_UNICODE 1
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 1
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
#endif /* __PJ_COMPAT_OS_WINPHONE8_H__ */

View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_OS_UWP_H__
#define __PJ_COMPAT_OS_UWP_H__
/**
* @file os_winuwp.h
* @brief Describes Windows UWP operating system family specifics.
*/
#define PJ_OS_NAME "winuwp"
#define WIN32_LEAN_AND_MEAN
#define RPC_NO_WINDOWS_H
#define PJ_WIN32_WINNT 0x0602 /*_WIN32_WINNT_WIN8*/
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#define _WIN32_WINNT PJ_WIN32_WINNT
#endif
#define PJ_HAS_ARPA_INET_H 0
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 0 /* Must be zero, otherwise errno_test() fails. */
#define PJ_HAS_INTTYPES_H 1
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 0
#define PJ_HAS_NETINET_IN_H 0
#define PJ_HAS_NETINET_TCP_H 0
#define PJ_HAS_SETJMP_H 1
#define PJ_HAS_STDARG_H 1
#define PJ_HAS_STDDEF_H 1
#define PJ_HAS_STDIO_H 1
#define PJ_HAS_STDLIB_H 1
#define PJ_HAS_STRING_H 1
#define PJ_HAS_SYS_IOCTL_H 0
#define PJ_HAS_SYS_SELECT_H 0
#define PJ_HAS_SYS_SOCKET_H 0
#define PJ_HAS_SYS_TIME_H 0
#define PJ_HAS_SYS_TIMEB_H 0 /* Doesn't have sys/timeb.h */
#define PJ_HAS_SYS_TYPES_H 0 /* Doesn't have sys/types.h */
#define PJ_HAS_TIME_H 1
#define PJ_HAS_UNISTD_H 0
#define PJ_HAS_LIMITS_H 1
#define PJ_HAS_MSWSOCK_H 1
#define PJ_HAS_WINSOCK_H 0
#define PJ_HAS_WINSOCK2_H 1
#define PJ_SOCK_HAS_INET_ATON 0
/* Set 1 if native sockaddr_in has sin_len member.
* Default: 0
*/
#define PJ_SOCKADDR_HAS_LEN 0
/* Is errno a good way to retrieve OS errors? (no)
*/
#define PJ_HAS_ERRNO_VAR 0
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
#define PJ_HAS_SO_ERROR 0
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() or send() can not return immediately.
*/
#define PJ_BLOCKING_ERROR_VAL WSAEWOULDBLOCK
/* This value specifies the value set in errno by the OS when a non-blocking
* socket connect() can not get connected immediately.
*/
#define PJ_BLOCKING_CONNECT_ERROR_VAL WSAEWOULDBLOCK
/**
* If this macro is set, it tells select I/O Queue that select() needs to
* be given correct value of nfds (i.e. largest fd + 1). This requires
* select ioqueue to re-scan the descriptors on each registration and
* unregistration.
* If this macro is not set, then ioqueue will always give FD_SETSIZE for
* nfds argument when calling select().
*
* Default: 0
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* Endianness */
#ifndef PJ_IS_LITTLE_ENDIAN
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
#endif
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)
#endif
#define PJ_HAS_HIGH_RES_TIMER 1
#define PJ_HAS_MALLOC 1
#ifndef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
#endif
#define PJ_ATOMIC_VALUE_TYPE long
/* No console. */
#define PJ_TERM_HAS_COLOR 0
/* No rdtsc */
#define PJ_TIMESTAMP_USE_RDTSC 0
/* Native string is Unicode. */
#define PJ_NATIVE_STRING_IS_UNICODE 1
/* If 1, use Read/Write mutex emulation for platforms that don't support it */
#define PJ_EMULATE_RWMUTEX 1
/* If 1, pj_thread_create() should enforce the stack size when creating
* threads.
* Default: 0 (let OS decide the thread's stack size).
*/
#define PJ_THREAD_SET_STACK_SIZE 0
/* If 1, pj_thread_create() should allocate stack from the pool supplied.
* Default: 0 (let OS allocate memory for thread's stack).
*/
#define PJ_THREAD_ALLOCATE_STACK 0
#endif /* __PJ_COMPAT_OS_UWP_H__ */

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_RAND_H__
#define __PJ_COMPAT_RAND_H__
/**
* @file rand.h
* @brief Provides platform_rand() and platform_srand() functions.
*/
#if defined(PJ_HAS_STDLIB_H) && PJ_HAS_STDLIB_H != 0
/*
* Use stdlib based rand() and srand().
*/
# include <stdlib.h>
# define platform_srand srand
# if defined(RAND_MAX) && RAND_MAX <= 0xFFFF
/*
* When rand() is only 16 bit strong, double the strength
* by calling it twice!
*/
PJ_INLINE(int) platform_rand(void)
{
return ((rand() & 0xFFFF) << 16) | (rand() & 0xFFFF);
}
# else
# define platform_rand rand
# endif
#else
# warning "platform_rand() is not implemented"
# define platform_rand() 1
# define platform_srand(seed)
#endif
#endif /* __PJ_COMPAT_RAND_H__ */

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_SETJMP_H__
#define __PJ_COMPAT_SETJMP_H__
/**
* @file setjmp.h
* @brief Provides setjmp.h functionality.
*/
#if defined(PJ_HAS_SETJMP_H) && PJ_HAS_SETJMP_H != 0
# include <setjmp.h>
typedef jmp_buf pj_jmp_buf;
# ifndef pj_setjmp
# define pj_setjmp(buf) setjmp(buf)
# endif
# ifndef pj_longjmp
# define pj_longjmp(buf,d) longjmp(buf,d)
# endif
#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
/* Symbian framework don't use setjmp/longjmp */
#else
# warning "setjmp()/longjmp() is not implemented"
typedef int pj_jmp_buf[1];
# define pj_setjmp(buf) 0
# define pj_longjmp(buf,d) 0
#endif
#endif /* __PJ_COMPAT_SETJMP_H__ */

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_SIZE_T_H__
#define __PJ_COMPAT_SIZE_T_H__
/**
* @file size_t.h
* @brief Provides size_t type.
*/
#if PJ_HAS_STDDEF_H
# include <stddef.h>
#endif
#endif /* __PJ_COMPAT_SIZE_T_H__ */

View File

@@ -0,0 +1,223 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_SOCKET_H__
#define __PJ_COMPAT_SOCKET_H__
/**
* @file socket.h
* @brief Provides all socket related functions,data types, error codes, etc.
*/
#if defined(PJ_HAS_WINSOCK2_H) && PJ_HAS_WINSOCK2_H != 0
# include <winsock2.h>
#endif
#if defined(PJ_HAS_WINSOCK_H) && PJ_HAS_WINSOCK_H != 0
# include <winsock.h>
#endif
#if defined(PJ_HAS_WS2TCPIP_H) && PJ_HAS_WS2TCPIP_H != 0
# include <ws2tcpip.h>
#endif
#if (defined(PJ_WIN32_UWP) && PJ_WIN32_UWP!=0)
# include <in6addr.h>
#endif
/*
* IPv6 for Visual Studio's
*
* = Visual Studio 6 =
*
* Visual Studio 6 does not ship with IPv6 support, so you MUST
* download and install IPv6 Tehnology Preview (IPv6Kit) from:
* http://msdn.microsoft.com/downloads/sdks/platform/tpipv6/ReadMe.asp
* Then put IPv6Kit\inc in your Visual Studio include path.
*
* In addition, by default IPv6Kit does not want to install on
* Windows 2000 SP4. Please see:
* http://msdn.microsoft.com/downloads/sdks/platform/tpipv6/faq.asp
* on how to install IPv6Kit on Win2K SP4.
*
*
* = Visual Studio 2003, 2005 (including Express) =
*
* These VS uses Microsoft Platform SDK for Windows Server 2003 SP1, and
* it has built-in IPv6 support.
*/
#if defined(_MSC_VER) && defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0
# ifndef s_addr
# define s_addr S_un.S_addr
# endif
# if !defined(IPPROTO_IPV6) && (_WIN32_WINNT == 0x0500)
/* Need to download and install IPv6Kit for this platform.
* Please see the comments above about Visual Studio 6.
*/
# include <tpipv6.h>
# endif
# define PJ_SOCK_HAS_GETADDRINFO 1
#endif /* _MSC_VER */
#if defined(PJ_HAS_SYS_TYPES_H) && PJ_HAS_SYS_TYPES_H != 0
# include <sys/types.h>
#endif
#if defined(PJ_HAS_SYS_SOCKET_H) && PJ_HAS_SYS_SOCKET_H != 0
# include <sys/socket.h>
#endif
#if defined(PJ_HAS_LINUX_SOCKET_H) && PJ_HAS_LINUX_SOCKET_H != 0
# include <linux/socket.h>
#endif
#if defined(PJ_HAS_SYS_SELECT_H) && PJ_HAS_SYS_SELECT_H != 0
# include <sys/select.h>
#endif
#if defined(PJ_HAS_NETINET_IN_H) && PJ_HAS_NETINET_IN_H != 0
# include <netinet/in.h>
#endif
#if defined(PJ_HAS_NETINET_IN_SYSTM_H) && PJ_HAS_NETINET_IN_SYSTM_H != 0
/* Required to include netinet/ip.h in FreeBSD 7.0 */
# include <netinet/in_systm.h>
#endif
#if defined(PJ_HAS_NETINET_IP_H) && PJ_HAS_NETINET_IP_H != 0
/* To pull in IPTOS_* constants */
# include <netinet/ip.h>
#endif
#if defined(PJ_HAS_NETINET_TCP_H) && PJ_HAS_NETINET_TCP_H != 0
/* To pull in TCP_NODELAY constants */
# include <netinet/tcp.h>
#endif
#if defined(PJ_HAS_NET_IF_H) && PJ_HAS_NET_IF_H != 0
/* For interface enumeration in ip_helper */
# include <net/if.h>
#endif
#if defined(PJ_HAS_IFADDRS_H) && PJ_HAS_IFADDRS_H != 0
/* Interface enum with getifaddrs() which works with IPv6 */
# include <ifaddrs.h>
#endif
#if defined(PJ_HAS_ARPA_INET_H) && PJ_HAS_ARPA_INET_H != 0
# include <arpa/inet.h>
#endif
#if defined(PJ_HAS_SYS_IOCTL_H) && PJ_HAS_SYS_IOCTL_H != 0
# include <sys/ioctl.h> /* FBIONBIO */
#endif
#if defined(PJ_HAS_ERRNO_H) && PJ_HAS_ERRNO_H != 0
# include <errno.h>
#endif
#if defined(PJ_HAS_NETDB_H) && PJ_HAS_NETDB_H != 0
# include <netdb.h>
#endif
#if defined(PJ_HAS_UNISTD_H) && PJ_HAS_UNISTD_H != 0
# include <unistd.h>
#endif
#if defined(PJ_HAS_SYS_FILIO_H) && PJ_HAS_SYS_FILIO_H != 0
# include <sys/filio.h>
#endif
#if defined(PJ_HAS_SYS_SOCKIO_H) && PJ_HAS_SYS_SOCKIO_H != 0
# include <sys/sockio.h>
#endif
/*
* Define common errors.
*/
#if (defined(PJ_WIN32) && PJ_WIN32!=0) || \
(defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0) || \
(defined(PJ_WIN64) && PJ_WIN64!=0)
# define OSERR_EWOULDBLOCK WSAEWOULDBLOCK
# define OSERR_EINPROGRESS WSAEINPROGRESS
# define OSERR_ECONNRESET WSAECONNRESET
# define OSERR_ENOTCONN WSAENOTCONN
# define OSERR_EAFNOSUPPORT WSAEAFNOSUPPORT
# define OSERR_ENOPROTOOPT WSAENOPROTOOPT
#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
# define OSERR_EWOULDBLOCK -1
# define OSERR_EINPROGRESS -1
# define OSERR_ECONNRESET -1
# define OSERR_ENOTCONN -1
# define OSERR_EAFNOSUPPORT -1
# define OSERR_ENOPROTOOPT -1
#else
# define OSERR_EWOULDBLOCK EWOULDBLOCK
# define OSERR_EINPROGRESS EINPROGRESS
# define OSERR_ECONNRESET ECONNRESET
# define OSERR_ENOTCONN ENOTCONN
# define OSERR_EAFNOSUPPORT EAFNOSUPPORT
# define OSERR_ENOPROTOOPT ENOPROTOOPT
#endif
/*
* And undefine these..
* Note (see issue #2311): unfortunately, this may cause build failure
* to anyone who uses these standard macros.
*/
//#undef s_addr
//#undef s6_addr
//#undef sin_zero
/*
* This will finally be obsoleted, since it should be declared in
* os_auto.h
*/
#if !defined(PJ_HAS_SOCKLEN_T) || PJ_HAS_SOCKLEN_T==0
typedef int socklen_t;
#endif
/* Regarding sin_len member of sockaddr_in:
* BSD systems (including MacOS X requires that the sin_len member of
* sockaddr_in be set to sizeof(sockaddr_in), while other systems (Windows
* and Linux included) do not.
*
* To maintain compatibility between systems, PJLIB will automatically
* set this field before invoking native OS socket API, and it will
* always reset the field to zero before returning pj_sockaddr_in to
* application (such as in pj_getsockname() and pj_recvfrom()).
*
* Application MUST always set this field to zero.
*
* This way we can avoid hard to find problem such as when the socket
* address is used as hash table key.
*/
#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
# define PJ_SOCKADDR_SET_LEN(addr,len) (((pj_addr_hdr*)(addr))->sa_zero_len=(len))
# define PJ_SOCKADDR_RESET_LEN(addr) (((pj_addr_hdr*)(addr))->sa_zero_len=0)
#else
# define PJ_SOCKADDR_SET_LEN(addr,len)
# define PJ_SOCKADDR_RESET_LEN(addr)
#endif
#endif /* __PJ_COMPAT_SOCKET_H__ */

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_STDARG_H__
#define __PJ_COMPAT_STDARG_H__
/**
* @file stdarg.h
* @brief Provides stdarg functionality.
*/
#if defined(PJ_HAS_STDARG_H) && PJ_HAS_STDARG_H != 0
# include <stdarg.h>
#endif
#endif /* __PJ_COMPAT_STDARG_H__ */

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_STDFILEIO_H__
#define __PJ_COMPAT_STDFILEIO_H__
/**
* @file stdfileio.h
* @brief Compatibility for ANSI file I/O like fputs, fflush, etc.
*/
#if defined(PJ_HAS_STDIO_H) && PJ_HAS_STDIO_H != 0
# include <stdio.h>
#endif
#endif /* __PJ_COMPAT_STDFILEIO_H__ */

View File

@@ -0,0 +1,178 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_STRING_H__
#define __PJ_COMPAT_STRING_H__
/**
* @file string.h
* @brief Provides string manipulation functions found in ANSI string.h.
*/
#if defined(PJ_HAS_STRING_H) && PJ_HAS_STRING_H != 0
# include <string.h>
#else
PJ_DECL(int) strcasecmp(const char *s1, const char *s2);
PJ_DECL(int) strncasecmp(const char *s1, const char *s2, int len);
#endif
/* For sprintf family */
#include <stdio.h>
/* On WinCE, string stuffs are declared in stdlib.h */
#if defined(PJ_HAS_STDLIB_H) && PJ_HAS_STDLIB_H!=0
# include <stdlib.h>
#endif
#if defined(_MSC_VER)
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
/* snprintf() and vsnprintf() are available since Visual Studio 2015 */
#if _MSC_VER < 1900
# define snprintf _snprintf
# define vsnprintf _vsnprintf
#endif
# define snwprintf _snwprintf
# define wcsicmp _wcsicmp
# define wcsnicmp _wcsnicmp
#else
# define stricmp strcasecmp
# define strnicmp strncasecmp
# if defined(PJ_NATIVE_STRING_IS_UNICODE) && PJ_NATIVE_STRING_IS_UNICODE!=0
# error "Implement Unicode string functions"
# endif
#endif
#define pj_ansi_strcmp strcmp
#define pj_ansi_strncmp strncmp
#define pj_ansi_strlen strlen
#if defined(PJ_BAN_STRCPY) && PJ_BAN_STRCPY
/* Use pj_ansi_strxcpy() instead */
# define strcpy error__strcpy_is_banned
# define pj_ansi_strcpy error__strcpy_is_banned
#else
# define pj_ansi_strcpy strcpy
#endif
#if defined(PJ_BAN_STRNCPY) && PJ_BAN_STRNCPY
/* Use pj_ansi_strxcpy() instead */
# define strncpy error__strncpy_is_banned
# define pj_ansi_strncpy error__strncpy_is_banned
#else
# define pj_ansi_strncpy strncpy
#endif
#if defined(PJ_BAN_STRCAT) && PJ_BAN_STRCAT
/* Use pj_ansi_strxcat() instead */
# define strcat error__strcat_is_banned
# define pj_ansi_strcat error__strcat_is_banned
#else
# define pj_ansi_strcat strcat
#endif
#define pj_ansi_strstr strstr
#define pj_ansi_strchr strchr
#define pj_ansi_strcasecmp strcasecmp
#define pj_ansi_stricmp strcasecmp
#define pj_ansi_strncasecmp strncasecmp
#define pj_ansi_strnicmp strncasecmp
#if defined(PJ_BAN_SPRINTF) && PJ_BAN_SPRINTF
/* Use pj_ansi_snprintf() instead */
# define sprintf error__sprintf_is_banned
# define pj_ansi_sprintf error__sprintf_is_banned
#else
# define pj_ansi_sprintf sprintf
#endif
#if defined(PJ_HAS_NO_SNPRINTF) && PJ_HAS_NO_SNPRINTF != 0
# include <pj/types.h>
# include <pj/compat/stdarg.h>
PJ_BEGIN_DECL
PJ_DECL(int) snprintf(char*s1, pj_size_t len, const char*s2, ...);
PJ_DECL(int) vsnprintf(char*s1, pj_size_t len, const char*s2, va_list arg);
PJ_END_DECL
#endif
#define pj_ansi_snprintf snprintf
#if defined(PJ_BAN_VSPRINTF) && PJ_BAN_VSPRINTF
/* Use pj_ansi_vsnprintf() instead */
# define vsprintf error__vsprintf_is_banned
# define pj_ansi_vsprintf error__vsprintf_is_banned
#else
# define pj_ansi_vsprintf vsprintf
#endif
#define pj_ansi_vsnprintf vsnprintf
#define pj_unicode_strcmp wcscmp
#define pj_unicode_strncmp wcsncmp
#define pj_unicode_strlen wcslen
#define pj_unicode_strcpy wcscpy
#define pj_unicode_strncpy wcsncpy
#define pj_unicode_strcat wcscat
#define pj_unicode_strstr wcsstr
#define pj_unicode_strchr wcschr
#define pj_unicode_strcasecmp wcsicmp
#define pj_unicode_stricmp wcsicmp
#define pj_unicode_strncasecmp wcsnicmp
#define pj_unicode_strnicmp wcsnicmp
#define pj_unicode_sprintf swprintf
#define pj_unicode_snprintf snwprintf
#define pj_unicode_vsprintf vswprintf
#define pj_unicode_vsnprintf vsnwprintf
#if defined(PJ_NATIVE_STRING_IS_UNICODE) && PJ_NATIVE_STRING_IS_UNICODE!=0
# define pj_native_strcmp pj_unicode_strcmp
# define pj_native_strncmp pj_unicode_strncmp
# define pj_native_strlen pj_unicode_strlen
# define pj_native_strcpy pj_unicode_strcpy
# define pj_native_strncpy pj_unicode_strncpy
# define pj_native_strcat pj_unicode_strcat
# define pj_native_strstr pj_unicode_strstr
# define pj_native_strchr pj_unicode_strchr
# define pj_native_strcasecmp pj_unicode_strcasecmp
# define pj_native_stricmp pj_unicode_stricmp
# define pj_native_strncasecmp pj_unicode_strncasecmp
# define pj_native_strnicmp pj_unicode_strnicmp
# define pj_native_sprintf pj_unicode_sprintf
# define pj_native_snprintf pj_unicode_snprintf
# define pj_native_vsprintf pj_unicode_vsprintf
# define pj_native_vsnprintf pj_unicode_vsnprintf
#else
# define pj_native_strcmp pj_ansi_strcmp
# define pj_native_strncmp pj_ansi_strncmp
# define pj_native_strlen pj_ansi_strlen
# define pj_native_strcpy pj_ansi_strcpy
# define pj_native_strncpy pj_ansi_strncpy
# define pj_native_strcat pj_ansi_strcat
# define pj_native_strstr pj_ansi_strstr
# define pj_native_strchr pj_ansi_strchr
# define pj_native_strcasecmp pj_ansi_strcasecmp
# define pj_native_stricmp pj_ansi_stricmp
# define pj_native_strncasecmp pj_ansi_strncasecmp
# define pj_native_strnicmp pj_ansi_strnicmp
# define pj_native_sprintf pj_ansi_sprintf
# define pj_native_snprintf pj_ansi_snprintf
# define pj_native_vsprintf pj_ansi_vsprintf
# define pj_native_vsnprintf pj_ansi_vsnprintf
#endif
#endif /* __PJ_COMPAT_STRING_H__ */

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_COMPAT_TIME_H__
#define __PJ_COMPAT_TIME_H__
/**
* @file time.h
* @brief Provides ftime() and localtime() etc functions.
*/
#if defined(PJ_HAS_TIME_H) && PJ_HAS_TIME_H != 0
# include <time.h>
#endif
#if defined(PJ_HAS_SYS_TIME_H) && PJ_HAS_SYS_TIME_H != 0
# include <sys/time.h>
#endif
#if defined(PJ_HAS_SYS_TIMEB_H) && PJ_HAS_SYS_TIMEB_H != 0
# include <sys/timeb.h>
#endif
#endif /* __PJ_COMPAT_TIME_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,485 @@
/*
* This file contains several sample settings especially for Windows
* Mobile and Symbian targets. You can include this file in your
* <pj/config_site.h> file.
*
* The Windows Mobile and Symbian settings will be activated
* automatically if you include this file.
*
* In addition, you may specify one of these macros (before including
* this file) to activate additional settings:
*
* #define PJ_CONFIG_NOKIA_APS_DIRECT
* Use this macro to activate the APS-Direct feature. Please see
* http://trac.pjsip.org/repos/wiki/Nokia_APS_VAS_Direct for more
* info.
*
* #define PJ_CONFIG_WIN32_WMME_DIRECT
* Configuration to activate "APS-Direct" media mode on Windows or
* Windows Mobile, useful for testing purposes only.
*/
/*
* Typical configuration for WinCE target.
*/
#if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
/*
* PJLIB settings.
*/
/* Disable floating point support */
#define PJ_HAS_FLOATING_POINT 0
/*
* PJMEDIA settings
*/
/* Select codecs to disable */
#define PJMEDIA_HAS_L16_CODEC 0
#define PJMEDIA_HAS_ILBC_CODEC 0
/* We probably need more buffers on WM, so increase the limit */
#define PJMEDIA_SOUND_BUFFER_COUNT 32
/* Fine tune Speex's default settings for best performance/quality */
#define PJMEDIA_CODEC_SPEEX_DEFAULT_QUALITY 5
/* For CPU reason, disable speex AEC and use the echo suppressor. */
#define PJMEDIA_HAS_SPEEX_AEC 0
/* Previously, resampling is disabled due to performance reason and
* this condition prevented some 'light' wideband codecs (e.g: G722.1)
* to work along with narrowband codecs. Lately, some tests showed
* that 16kHz <-> 8kHz resampling using libresample small filter was
* affordable on ARM9 260 MHz, so here we decided to enable resampling.
* Note that it is important to make sure that libresample is created
* using small filter. For example PJSUA_DEFAULT_CODEC_QUALITY must
* be set to 3 or 4 so pjsua-lib will apply small filter resampling.
*/
//#define PJMEDIA_RESAMPLE_IMP PJMEDIA_RESAMPLE_NONE
#define PJMEDIA_RESAMPLE_IMP PJMEDIA_RESAMPLE_LIBRESAMPLE
/* Use the lighter WSOLA implementation */
#define PJMEDIA_WSOLA_IMP PJMEDIA_WSOLA_IMP_WSOLA_LITE
/*
* PJSIP settings.
*/
/* Set maximum number of dialog/transaction/calls to minimum to reduce
* memory usage
*/
#define PJSIP_MAX_TSX_COUNT 31
#define PJSIP_MAX_DIALOG_COUNT 31
#define PJSUA_MAX_CALLS 4
/*
* PJSUA settings
*/
/* Default codec quality, previously was set to 5, however it is now
* set to 4 to make sure pjsua instantiates resampler with small filter.
*/
#define PJSUA_DEFAULT_CODEC_QUALITY 4
/* Set maximum number of objects to minimum to reduce memory usage */
#define PJSUA_MAX_ACC 4
#define PJSUA_MAX_PLAYERS 4
#define PJSUA_MAX_RECORDERS 4
#define PJSUA_MAX_CONF_PORTS (PJSUA_MAX_CALLS+2*PJSUA_MAX_PLAYERS)
#define PJSUA_MAX_BUDDIES 32
#endif /* PJ_WIN32_WINCE */
/*
* Typical configuration for Symbian OS target
*/
#if defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
/*
* PJLIB settings.
*/
/* Disable floating point support */
#define PJ_HAS_FLOATING_POINT 0
/* Misc PJLIB setting */
#define PJ_MAXPATH 80
/* This is important for Symbian. Symbian lacks vsnprintf(), so
* if the log buffer is not long enough it's possible that
* large incoming packet will corrupt memory when the log tries
* to log the packet.
*/
#define PJ_LOG_MAX_SIZE (PJSIP_MAX_PKT_LEN+500)
/* Since we don't have threads, log buffer can use static buffer
* rather than stack
*/
#define PJ_LOG_USE_STACK_BUFFER 0
/* Disable check stack since it increases footprint */
#define PJ_OS_HAS_CHECK_STACK 0
/*
* PJMEDIA settings
*/
/* Disable non-Symbian audio devices */
#define PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 0
#define PJMEDIA_AUDIO_DEV_HAS_WMME 0
/* Select codecs to disable */
#define PJMEDIA_HAS_L16_CODEC 0
#define PJMEDIA_HAS_ILBC_CODEC 0
#define PJMEDIA_HAS_G722_CODEC 0
/* Fine tune Speex's default settings for best performance/quality */
#define PJMEDIA_CODEC_SPEEX_DEFAULT_QUALITY 5
/* For CPU reason, disable speex AEC and use the echo suppressor. */
#define PJMEDIA_HAS_SPEEX_AEC 0
/* Previously, resampling is disabled due to performance reason and
* this condition prevented some 'light' wideband codecs (e.g: G722.1)
* to work along with narrowband codecs. Lately, some tests showed
* that 16kHz <-> 8kHz resampling using libresample small filter was
* affordable on ARM9 222 MHz, so here we decided to enable resampling.
* Note that it is important to make sure that libresample is created
* using small filter. For example PJSUA_DEFAULT_CODEC_QUALITY must
* be set to 3 or 4 so pjsua-lib will apply small filter resampling.
*/
//#define PJMEDIA_RESAMPLE_IMP PJMEDIA_RESAMPLE_NONE
#define PJMEDIA_RESAMPLE_IMP PJMEDIA_RESAMPLE_LIBRESAMPLE
/* Use the lighter WSOLA implementation */
#define PJMEDIA_WSOLA_IMP PJMEDIA_WSOLA_IMP_WSOLA_LITE
/* We probably need more buffers especially if MDA audio backend
* is used, so increase the limit
*/
#define PJMEDIA_SOUND_BUFFER_COUNT 32
/*
* PJSIP settings.
*/
/* Disable safe module access, since we don't use multithreading */
#define PJSIP_SAFE_MODULE 0
/* Use large enough packet size */
#define PJSIP_MAX_PKT_LEN 2000
/* Symbian has problem with too many large blocks */
#define PJSIP_POOL_LEN_ENDPT 1000
#define PJSIP_POOL_INC_ENDPT 1000
#define PJSIP_POOL_RDATA_LEN 2000
#define PJSIP_POOL_RDATA_INC 2000
#define PJSIP_POOL_LEN_TDATA 2000
#define PJSIP_POOL_INC_TDATA 512
#define PJSIP_POOL_LEN_UA 2000
#define PJSIP_POOL_INC_UA 1000
#define PJSIP_POOL_TSX_LAYER_LEN 256
#define PJSIP_POOL_TSX_LAYER_INC 256
#define PJSIP_POOL_TSX_LEN 512
#define PJSIP_POOL_TSX_INC 128
/*
* PJSUA settings.
*/
/* Default codec quality, previously was set to 5, however it is now
* set to 4 to make sure pjsua instantiates resampler with small filter.
*/
#define PJSUA_DEFAULT_CODEC_QUALITY 4
/* Set maximum number of dialog/transaction/calls to minimum */
#define PJSIP_MAX_TSX_COUNT 31
#define PJSIP_MAX_DIALOG_COUNT 31
#define PJSUA_MAX_CALLS 4
/* Other pjsua settings */
#define PJSUA_MAX_ACC 4
#define PJSUA_MAX_PLAYERS 4
#define PJSUA_MAX_RECORDERS 4
#define PJSUA_MAX_CONF_PORTS (PJSUA_MAX_CALLS+2*PJSUA_MAX_PLAYERS)
#define PJSUA_MAX_BUDDIES 32
#endif
/*
* Additional configuration to activate APS-Direct feature for
* Nokia S60 target
*
* Please see http://trac.pjsip.org/repos/wiki/Nokia_APS_VAS_Direct
*/
#ifdef PJ_CONFIG_NOKIA_APS_DIRECT
/* MUST use switchboard rather than the conference bridge */
#define PJMEDIA_CONF_USE_SWITCH_BOARD 1
/* Enable APS sound device backend and disable MDA & VAS */
#define PJMEDIA_AUDIO_DEV_HAS_SYMB_MDA 0
#define PJMEDIA_AUDIO_DEV_HAS_SYMB_APS 1
#define PJMEDIA_AUDIO_DEV_HAS_SYMB_VAS 0
/* Enable passthrough codec framework */
#define PJMEDIA_HAS_PASSTHROUGH_CODECS 1
/* And selectively enable which codecs are supported by the handset */
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMU 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMA 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_G729 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC 1
#endif
/*
* Additional configuration to activate VAS-Direct feature for
* Nokia S60 target
*
* Please see http://trac.pjsip.org/repos/wiki/Nokia_APS_VAS_Direct
*/
#ifdef PJ_CONFIG_NOKIA_VAS_DIRECT
/* MUST use switchboard rather than the conference bridge */
#define PJMEDIA_CONF_USE_SWITCH_BOARD 1
/* Enable VAS sound device backend and disable MDA & APS */
#define PJMEDIA_AUDIO_DEV_HAS_SYMB_MDA 0
#define PJMEDIA_AUDIO_DEV_HAS_SYMB_APS 0
#define PJMEDIA_AUDIO_DEV_HAS_SYMB_VAS 1
/* Enable passthrough codec framework */
#define PJMEDIA_HAS_PASSTHROUGH_CODECS 1
/* And selectively enable which codecs are supported by the handset */
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMU 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMA 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_G729 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC 1
#endif
/*
* Configuration to activate "APS-Direct" media mode on Windows,
* useful for testing purposes only.
*/
#ifdef PJ_CONFIG_WIN32_WMME_DIRECT
/* MUST use switchboard rather than the conference bridge */
#define PJMEDIA_CONF_USE_SWITCH_BOARD 1
/* Only WMME supports the "direct" feature */
#define PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 0
#define PJMEDIA_AUDIO_DEV_HAS_WMME 1
/* Enable passthrough codec framework */
#define PJMEDIA_HAS_PASSTHROUGH_CODECS 1
/* Only PCMA and PCMU are supported by WMME-direct */
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMU 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMA 1
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR 0
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_G729 0
#define PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC 0
#endif
/*
* iPhone sample settings.
*/
#if PJ_CONFIG_IPHONE
/*
* PJLIB settings.
*/
/* Both armv6 and armv7 has FP hardware support.
* See https://github.com/pjsip/pjproject/issues/1589 for more info
*/
#define PJ_HAS_FLOATING_POINT 1
/*
* PJMEDIA settings
*/
/* We have our own native CoreAudio backend */
#define PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 0
#define PJMEDIA_AUDIO_DEV_HAS_WMME 0
#define PJMEDIA_AUDIO_DEV_HAS_COREAUDIO 1
/* The CoreAudio backend has built-in echo canceller! */
#define PJMEDIA_HAS_SPEEX_AEC 0
/* Disable some codecs */
#define PJMEDIA_HAS_L16_CODEC 0
//#define PJMEDIA_HAS_G722_CODEC 0
/* Use the built-in CoreAudio's iLBC codec (yay!) */
#define PJMEDIA_HAS_ILBC_CODEC 1
#define PJMEDIA_ILBC_CODEC_USE_COREAUDIO 1
/* Fine tune Speex's default settings for best performance/quality */
#define PJMEDIA_CODEC_SPEEX_DEFAULT_QUALITY 5
/*
* PJSIP settings.
*/
/* Increase allowable packet size, just in case */
//#define PJSIP_MAX_PKT_LEN 2000
/*
* PJSUA settings.
*/
/* Default codec quality, previously was set to 5, however it is now
* set to 4 to make sure pjsua instantiates resampler with small filter.
*/
#define PJSUA_DEFAULT_CODEC_QUALITY 4
/* Set maximum number of dialog/transaction/calls to minimum */
#define PJSIP_MAX_TSX_COUNT 31
#define PJSIP_MAX_DIALOG_COUNT 31
#define PJSUA_MAX_CALLS 4
/* Other pjsua settings */
#define PJSUA_MAX_ACC 4
#define PJSUA_MAX_PLAYERS 4
#define PJSUA_MAX_RECORDERS 4
#define PJSUA_MAX_CONF_PORTS (PJSUA_MAX_CALLS+2*PJSUA_MAX_PLAYERS)
#define PJSUA_MAX_BUDDIES 32
#endif
/*
* Android sample settings.
*/
#if PJ_CONFIG_ANDROID
/*
* PJLIB settings.
*/
/* Disable floating point support */
#undef PJ_HAS_FLOATING_POINT
#define PJ_HAS_FLOATING_POINT 0
/*
* PJMEDIA settings
*/
/* We have our own OpenSL ES backend */
#define PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 0
#define PJMEDIA_AUDIO_DEV_HAS_WMME 0
#define PJMEDIA_AUDIO_DEV_HAS_OPENSL 0
#define PJMEDIA_AUDIO_DEV_HAS_ANDROID_JNI 1
/* Disable some codecs */
#define PJMEDIA_HAS_L16_CODEC 0
//#define PJMEDIA_HAS_G722_CODEC 0
/* Fine tune Speex's default settings for best performance/quality */
#define PJMEDIA_CODEC_SPEEX_DEFAULT_QUALITY 5
/*
* PJSIP settings.
*/
/* Increase allowable packet size, just in case */
//#define PJSIP_MAX_PKT_LEN 2000
/*
* PJSUA settings.
*/
/* Default codec quality, previously was set to 5, however it is now
* set to 4 to make sure pjsua instantiates resampler with small filter.
*/
#define PJSUA_DEFAULT_CODEC_QUALITY 4
/* Set maximum number of dialog/transaction/calls to minimum */
#define PJSIP_MAX_TSX_COUNT 31
#define PJSIP_MAX_DIALOG_COUNT 31
#define PJSUA_MAX_CALLS 4
/* Separate worker thread for timer and ioqueue */
// #define PJSUA_SEPARATE_WORKER_FOR_TIMER 1
/* Other pjsua settings */
#define PJSUA_MAX_ACC 4
#define PJSUA_MAX_PLAYERS 4
#define PJSUA_MAX_RECORDERS 4
#define PJSUA_MAX_CONF_PORTS (PJSUA_MAX_CALLS+2*PJSUA_MAX_PLAYERS)
#define PJSUA_MAX_BUDDIES 32
#endif
/*
* BB10
*/
#if defined(PJ_CONFIG_BB10) && PJ_CONFIG_BB10
/* Quality 3 - 4 to use resampling small filter */
#define PJSUA_DEFAULT_CODEC_QUALITY 4
#define PJMEDIA_HAS_LEGACY_SOUND_API 0
#undef PJMEDIA_HAS_SPEEX_AEC
#define PJMEDIA_HAS_SPEEX_AEC 0
#undef PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO
#define PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 0
#undef PJMEDIA_AUDIO_DEV_HAS_ALSA
#define PJMEDIA_AUDIO_DEV_HAS_ALSA 0
#endif
/*
* Minimum size
*/
#ifdef PJ_CONFIG_MINIMAL_SIZE
# undef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
# define PJ_LOG_MAX_LEVEL 0
# define PJ_HAS_ERROR_STRING 0
# undef PJ_IOQUEUE_MAX_HANDLES
/* Putting max handles to lower than 32 will make pj_fd_set_t size smaller
* than native fdset_t and will trigger assertion on sock_select.c.
*/
# define PJ_IOQUEUE_MAX_HANDLES 32
# define PJ_CRC32_HAS_TABLES 0
# define PJSIP_MAX_TSX_COUNT 15
# define PJSIP_MAX_DIALOG_COUNT 15
# define PJSIP_UDP_SO_SNDBUF_SIZE 4000
# define PJSIP_UDP_SO_RCVBUF_SIZE 4000
# define PJMEDIA_HAS_ALAW_ULAW_TABLE 0
#elif defined(PJ_CONFIG_MAXIMUM_SPEED)
# define PJ_SCANNER_USE_BITWISE 0
# undef PJ_OS_HAS_CHECK_STACK
# define PJ_OS_HAS_CHECK_STACK 0
# define PJ_LOG_MAX_LEVEL 3
# define PJ_IOQUEUE_MAX_HANDLES 5000
# define PJSIP_MAX_TSX_COUNT ((640*1024)-1)
# define PJSIP_MAX_DIALOG_COUNT ((640*1024)-1)
# define PJSIP_UDP_SO_SNDBUF_SIZE (24*1024*1024)
# define PJSIP_UDP_SO_RCVBUF_SIZE (24*1024*1024)
# define PJ_DEBUG 0
# define PJSIP_SAFE_MODULE 0
# define PJ_HAS_STRICMP_ALNUM 0
# define PJSIP_UNESCAPE_IN_PLACE 1
# if defined(PJ_WIN32) || defined(PJ_WIN64)
# define PJSIP_MAX_NET_EVENTS 10
# endif
# define PJSUA_MAX_CALLS 512
#endif

View File

@@ -0,0 +1,11 @@
#define PJMEDIA_SRTP_HAS_DTLS 1
#define PJMEDIA_HAS_WEBRTC_AEC 1
#define PJMEDIA_CODEC_L16_HAS_8KHZ_MONO 1
#define PJMEDIA_CODEC_L16_HAS_8KHZ_STEREO 1
#define PJMEDIA_CODEC_L16_HAS_16KHZ_MONO 1
#define PJMEDIA_CODEC_L16_HAS_16KHZ_STEREO 1
#define PJMEDIA_CODEC_L16_HAS_48KHZ_MONO 1
#define PJMEDIA_CODEC_L16_HAS_48KHZ_STEREO 1
#define PJMEDIA_HAS_G7221_CODEC 1
#define PJMEDIA_HAS_G722_CODEC 1
#define PJ_EXCLUDE_BENCHMARK_TESTS 1

View File

@@ -0,0 +1,174 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_CTYPE_H__
#define __PJ_CTYPE_H__
/**
* @file ctype.h
* @brief C type helper macros.
*/
#include <pj/types.h>
#include <pj/compat/ctype.h>
PJ_BEGIN_DECL
/**
* @defgroup pj_ctype ctype - Character Type
* @ingroup PJ_MISC
* @{
*
* This module contains several inline functions/macros for testing or
* manipulating character types. It is provided in PJLIB because PJLIB
* must not depend to LIBC.
*/
/**
* Returns a non-zero value if either isalpha or isdigit is true for c.
* @param c The integer character to test.
* @return Non-zero value if either isalpha or isdigit is true for c.
*/
PJ_INLINE(int) pj_isalnum(unsigned char c) { return isalnum(c); }
/**
* Returns a non-zero value if c is a particular representation of an
* alphabetic character.
* @param c The integer character to test.
* @return Non-zero value if c is a particular representation of an
* alphabetic character.
*/
PJ_INLINE(int) pj_isalpha(unsigned char c) { return isalpha(c); }
/**
* Returns a non-zero value if c is a particular representation of an
* ASCII character.
* @param c The integer character to test.
* @return Non-zero value if c is a particular representation of
* an ASCII character.
*/
PJ_INLINE(int) pj_isascii(unsigned char c) { return c<128; }
/**
* Returns a non-zero value if c is a particular representation of
* a decimal-digit character.
* @param c The integer character to test.
* @return Non-zero value if c is a particular representation of
* a decimal-digit character.
*/
PJ_INLINE(int) pj_isdigit(unsigned char c) { return isdigit(c); }
/**
* Returns a non-zero value if c is a particular representation of
* a space character (0x09 - 0x0D or 0x20).
* @param c The integer character to test.
* @return Non-zero value if c is a particular representation of
* a space character (0x09 - 0x0D or 0x20).
*/
PJ_INLINE(int) pj_isspace(unsigned char c) { return isspace(c); }
/**
* Returns a non-zero value if c is a particular representation of
* a lowercase character.
* @param c The integer character to test.
* @return Non-zero value if c is a particular representation of
* a lowercase character.
*/
PJ_INLINE(int) pj_islower(unsigned char c) { return islower(c); }
/**
* Returns a non-zero value if c is a particular representation of
* a uppercase character.
* @param c The integer character to test.
* @return Non-zero value if c is a particular representation of
* a uppercase character.
*/
PJ_INLINE(int) pj_isupper(unsigned char c) { return isupper(c); }
/**
* Returns a non-zero value if c is a either a space (' ') or horizontal
* tab ('\\t') character.
* @param c The integer character to test.
* @return Non-zero value if c is a either a space (' ') or horizontal
* tab ('\\t') character.
*/
PJ_INLINE(int) pj_isblank(unsigned char c) { return (c==' ' || c=='\t'); }
/**
* Converts character to lowercase.
* @param c The integer character to convert.
* @return Lowercase character of c.
*/
PJ_INLINE(int) pj_tolower(unsigned char c) { return tolower(c); }
/**
* Converts character to uppercase.
* @param c The integer character to convert.
* @return Uppercase character of c.
*/
PJ_INLINE(int) pj_toupper(unsigned char c) { return toupper(c); }
/**
* Returns a non-zero value if c is a particular representation of
* an hexadecimal digit character.
* @param c The integer character to test.
* @return Non-zero value if c is a particular representation of
* an hexadecimal digit character.
*/
PJ_INLINE(int) pj_isxdigit(unsigned char c){ return isxdigit(c); }
/**
* Array of hex digits, in lowerspace.
*/
/*extern char pj_hex_digits[];*/
#define pj_hex_digits "0123456789abcdef"
/**
* Convert a value to hex representation.
* @param value Integral value to convert.
* @param p Buffer to hold the hex representation, which must be
* at least two bytes length.
*/
PJ_INLINE(void) pj_val_to_hex_digit(unsigned value, char *p)
{
*p++ = pj_hex_digits[ (value & 0xF0) >> 4 ];
*p = pj_hex_digits[ (value & 0x0F) ];
}
/**
* Convert hex digit c to integral value.
* @param c The hex digit character.
* @return The integral value between 0 and 15.
*/
PJ_INLINE(unsigned) pj_hex_digit_to_val(unsigned char c)
{
if (c <= '9')
return (c-'0') & 0x0F;
else if (c <= 'F')
return (c-'A'+10) & 0x0F;
else
return (c-'a'+10) & 0x0F;
}
/** @} */
PJ_END_DECL
#endif /* __PJ_CTYPE_H__ */

View File

@@ -0,0 +1,995 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_DOXYGEN_H__
#define __PJ_DOXYGEN_H__
/**
* @file doxygen.h
* @brief Doxygen's mainpage.
*/
/*////////////////////////////////////////////////////////////////////////// */
/*
INTRODUCTION PAGE
*/
/**
* @mainpage Welcome to PJLIB!
*
* @section intro_sec What is PJLIB
*
* PJLIB is an Open Source, small footprint framework library written in C for
* making scalable applications. Because of its small footprint, it can be used
* in embedded applications (we hope so!), but yet the library is also aimed for
* facilitating the creation of high performance protocol stacks.
*
* PJLIB is released under GPL terms.
*
* @section download_sec Download
*
* PJLIB and all documentation can be downloaded from
* http://www.pjsip.org.
*
*
* @section how_to_use_sec About This Documentation
*
* This document is generated directly from PJLIB source file using
* \a doxygen (http://www.doxygen.org). Doxygen is a great (and free!)
* tools for generating such documentation.
*
*
* @subsection find_samples_subsec How to Read This Document
*
* This documentation is laid out more to be a reference guide instead
* of tutorial, therefore first time users may find it difficult to
* grasp PJLIB by reading this document alone.
*
* However, we've tried our best to make this document easy to follow.
* For first time users, we would suggest that you follow these steps
* when reading this documentation:
*
* - continue reading this introduction chapter. At the end of this
* chapter, you'll find section called \ref pjlib_fundamentals_sec
* which should guide you to understand basic things about PJLIB.
*
* - find information about specific features that you want to use
* in PJLIB. Use the <b>Module Index</b> to find out about all
* features in PJLIB (if you're browsing the HTML documentation,
* click on the \a Module link on top of the page, or if you're
* reading the PDF documentation, click on \a Module \a Documentation
* on the navigation pane on the left).
*
* @subsection doc_organize_sec How To's
*
* Please find below links to specific tasks that you probably
* want to do:
*
* - <b>How to Build PJLIB</b>
*\n
* Please refer to \ref pjlib_build_sys_pg page for more information.
*
* - <b>How to Use PJLIB in My Application</b>
*\n
* Please refer to \ref configure_app_sec for more information.
*
* - <b>How to Port PJLIB</b>
*\n
* Please refer to \ref porting_pjlib_pg page.
*
* - <b>Where to Read Samples Documentation</b>
*\n
* Most of the modules provide link to the corresponding sample file.
* Alternatively, to get the list of all examples, you can click on
* <b>Related Pages</b> on the top of HTML document or on
* <b>PJLIB Page Documentation</b> on navigation pane of your PDF reader.
*
* - <b>How to Submit Code to PJLIB Project</b>
*\n
* Please read \ref pjlib_coding_convention_page before submitting
* your code. Send your code as patch against current Subversion tree
* to the appropriate mailing list.
*
*
* @section features_sec Features
*
* @subsection open_source_feat It's Open Source!
*
* PJLIB is currently released on GPL license, but other arrangements
* can be made with the author.
*
* @subsection extreme_portable_feat Extreme Portability
*
* PJLIB is designed to be extremely portable. It can run on any kind
* of processors (16-bit, 32-bit, or 64-bit, big or little endian, single
* or multi-processors) and operating systems. Floating point or no
* floating point. Multi-threading or not.
* It can even run in environment where no ANSI LIBC is available.
*
* Currently PJLIB is known to run on these platforms:
* - Win32/x86 (Win95/98/ME, NT/2000/XP/2003, mingw).
* - arm, WinCE and Windows Mobile.
* - Linux/x86, (user mode and as <b>kernel module</b>(!)).
* - Linux/alpha
* - Solaris/ultra.
* - MacOS X/powerpc
* - RTEMS (x86 and powerpc).
*
* And efforts is under way to port PJLIB on:
* - Symbian OS
*
*
* @subsection small_size_feat Small in Size
*
* One of the primary objectives is to have library that is small in size for
* typical embedded applications. As a rough guidance, we aim to keep the
* library size below 100KB for it to be considered as small.
* As the result, most of the functionalities in the library can be tailored
* to meet the requirements; user can enable/disable specific functionalities
* to get the desired size/performance/functionality balance.
*
* For more info, please see @ref pj_config.
*
*
* @subsection big_perform_feat Big in Performance
*
* Almost everything in PJLIB is designed to achieve the highest possible
* performance out of the target platform.
*
*
* @subsection no_dyn_mem No Dynamic Memory Allocations
*
* The central idea of PJLIB is that for applications to run as fast as it can,
* it should not use \a malloc() at all, but instead should get the memory
* from a preallocated storage pool. There are few things that can be
* optimized with this approach:
*
* - \a alloc() is a O(1) operation.
* - no mutex is used inside alloc(). It is assumed that synchronization
* will be used in higher abstraction by application anyway.
* - no \a free() is required. All chunks will be deleted when the pool is
* destroyed.
*
* The performance gained on some systems can be as high as 30x speed up
* against \a malloc() and \a free() on certain configurations, but of
* course your mileage may vary.
*
* For more information, see \ref PJ_POOL_GROUP
*
*
* @subsection os_abstract_feat Operating System Abstraction
*
* PJLIB has abstractions for features that are normally not portable
* across operating systems:
* - @ref PJ_THREAD
*\n
* Portable thread manipulation.
* - @ref PJ_TLS
*\n
* Storing data in thread's private data.
* - @ref PJ_MUTEX
*\n
* Mutual exclusion protection.
* - @ref PJ_SEM
*\n
* Semaphores.
* - @ref PJ_ATOMIC
*\n
* Atomic variables and their operations.
* - @ref PJ_CRIT_SEC
*\n
* Fast locking of critical sections.
* - @ref PJ_LOCK
*\n
* High level abstraction for lock objects.
* - @ref PJ_EVENT
*\n
* Event object.
* - @ref PJ_TIME
*\n
* Portable time manipulation.
* - @ref PJ_TIMESTAMP
*\n
* High resolution time value.
* - etc.
*
*
* @subsection ll_network_io_sec Low-Level Network I/O
*
* PJLIB has very portable abstraction and fairly complete set of API for
* doing network I/O communications. At the lowest level, PJLIB provides:
*
* - @ref PJ_SOCK
*\n
* A highly portable socket abstraction, runs on all kind of
* network APIs such as standard BSD socket, Windows socket, Linux
* \b kernel socket, PalmOS networking API, etc.
*
* - @ref pj_addr_resolve
*\n
* Portable address resolution, which implements #pj_gethostbyname().
*
* - @ref PJ_SOCK_SELECT
*\n
* A portable \a select() like API (#pj_sock_select()) which can be
* implemented with various back-end.
*
*
*
* @subsection timer_mgmt_sec Timer Management
*
* A passive framework for managing timer, see @ref PJ_TIMER for more info.
* There is also function to retrieve high resolution timestamp
* from the system (see @ref PJ_TIMESTAMP).
*
*
* @subsection data_struct_sec Various Data Structures
*
* Various data structures are provided in the library:
*
* - @ref PJ_PSTR
* - @ref PJ_ARRAY
* - @ref PJ_HASH
* - @ref PJ_LIST
* - @ref PJ_RBTREE
*
*
* @subsection exception_sec Exception Construct
*
* A convenient TRY/CATCH like construct to propagate errors, which by
* default are used by the @ref PJ_POOL_GROUP "memory pool" and
* the lexical scanner in pjlib-util. The exception
* construct can be used to write programs like below:
*
* <pre>
* #define SYNTAX_ERROR 1
*
* PJ_TRY {
* msg = NULL;
* msg = parse_msg(buf, len);
* }
* PJ_CATCH ( SYNTAX_ERROR ) {
* .. handle error ..
* }
* PJ_END;
* </pre>
*
* Please see @ref PJ_EXCEPT for more information.
*
*
* @subsection logging_sec Logging Facility
*
* PJLIB @ref PJ_LOG consists of macros to write logging information to
* some output device. Some of the features of the logging facility:
*
* - the verbosity can be fine-tuned both at compile time (to control
* the library size) or run-time (to control the verbosity of the
* information).
* - output device is configurable (e.g. stdout, printk, file, etc.)
* - log decoration is configurable.
*
* See @ref PJ_LOG for more information.
*
*
* @subsection guid_gen_sec Random and GUID Generation
*
* PJLIB provides facility to create random string
* (#pj_create_random_string()) or globally unique identifier
* (see @ref PJ_GUID).
*
*
*
* @section configure_app_sec Configuring Application to use PJLIB
*
* @subsection pjlib_compil_sec Building PJLIB
*
* Follow the instructions in \ref pjlib_build_sys_pg to build
* PJLIB.
*
* @subsection pjlib_compil_app_sec Building Applications with PJLIB
*
* Use the following settings when building applications with PJLIB.
*
* @subsubsection compil_inc_dir_sec Include Search Path
*
* Add this to your include search path ($PJLIB is PJLIB root directory):
* <pre>
* $PJLIB/include
* </pre>
*
* @subsubsection compil_inc_file_sec Include PJLIB Header
*
* To include all PJLIB headers:
* \verbatim
#include <pjlib.h>
\endverbatim
*
* Alternatively, you can include individual PJLIB headers like this:
* \verbatim
#include <pj/log.h>
#include <pj/os.h>
\endverbatim
*
*
* @subsubsection compil_lib_dir_sec Library Path
*
* Add this to your library search path:
* <pre>
* $PJLIB/lib
* </pre>
*
* Then add the appropriate PJLIB library to your link specification. For
* example, you would add \c libpj-i386-linux-gcc.a when you're building
* applications in Linux.
*
*
* @subsection pjlib_fundamentals_sec Principles in Using PJLIB
*
* Few things that you \b MUST do when using PJLIB, to make sure that
* you create trully portable applications.
*
* @subsubsection call_pjlib_init_sec Call pj_init()
*
* Before you do anything else, call \c pj_init(). This would make sure that
* PJLIB system is properly set up.
*
* @subsubsection no_ansi_subsec Do NOT Use ANSI C
*
* Contrary to popular teaching, ANSI C (and LIBC) is not the most portable
* library in the world, nor it's the most ubiquitous. For example, LIBC
* is not available in Linux kernel. Also normally LIBC will be excluded
* from compilation of RTOSes to reduce size.
*
* So for maximum portability, do NOT use ANSI C. Do not even try to include
* any other header files outside <include/pj>. Stick with the functionalities
* provided by PJLIB.
*
*
* @subsubsection string_rep_subsubsec Use pj_str_t instead of C Strings
*
* PJLIB uses pj_str_t instead of normal C strings. You SHOULD follow this
* convention too. Remember, ANSI string-h is not always available. And
* PJLIB string is faster!
*
* @subsubsection mem_alloc_subsubsec Use Pool for Memory Allocations
*
* You MUST NOT use \a malloc() or any other memory allocation functions.
* Use PJLIB @ref PJ_POOL_GROUP instead! It's faster and most portable.
*
* @subsection logging_subsubsec Use Logging for Text Display
*
* DO NOT use <stdio.h> for text output. Use PJLIB @ref PJ_LOG instead.
*
*
* @section porting_pjlib_sec0 Porting PJLIB
*
* Please see \ref porting_pjlib_pg page on more information to port
* PJLIB to new target.
*
* @section enjoy_sec Enjoy Using PJLIB!
*
* We hope that you find PJLIB usefull for your application. If you
* have any questions, suggestions, critics, bug fixes, or anything
* else, we would be happy to hear it.
*
* Enjoy using PJLIB!
*
* Benny Prijono < bennylp at pjsip dot org >
*/
/*////////////////////////////////////////////////////////////////////////// */
/*
CODING CONVENTION
*/
/**
* @page pjlib_coding_convention_page Coding Convention
*
* Before you submit your code/patches to be included with PJLIB, you must
* make sure that your code is compliant with PJLIB coding convention.
* <b>This is very important!</b> Otherwise we would not accept your code.
*
* @section coding_conv_editor_sec Editor Settings
*
* The single most important thing in the whole coding convention is editor
* settings. It's more important than the correctness of your code (bugs will
* only crash the system, but incorrect tab size is mental!).
*
* Kindly set your editor as follows:
* - tab size to \b 8.
* - indentation to \b 4.
*
* With \c vi, you can do it with:
* <pre>
* :se ts=8
* :se sts=4
* </pre>
*
* You should replace tab with eight spaces.
*
* @section coding_conv_detail_sec Coding Style
*
* Coding style MUST strictly follow K&R style. The rest of coding style
* must follow current style. You SHOULD be able to observe the style
* currently used by PJLIB from PJLIB sources, and apply the style to your
* code. If you're not able to do simple thing like to observe PJLIB
* coding style from the sources, then logic dictates that your ability to
* observe more difficult area in PJLIB such as memory allocation strategy,
* concurrency, etc is questionable.
*
* @section coding_conv_comment_sec Commenting Your Code
*
* Public API (e.g. in header files) MUST have doxygen compliant comments.
*
*/
/*////////////////////////////////////////////////////////////////////////// */
/*
BUILDING AND INSTALLING PJLIB
*/
/**
* @page pjlib_build_sys_pg Building, and Installing PJLIB
*
* @section build_sys_install_sec Build and Installation
*
* \note
* <b>The most up-to-date information on building and installing PJLIB
* should be found in the website, under "Getting Started" document.
* More over, the new PJLIB build system is now based on autoconf,
* so some of the information here might not be relevant anymore
* (although most still are, since the autoconf script still use
* the old Makefile system as the backend).</b>
*
* @subsection build_sys_install_win32_sec Visual Studio
*
* The PJLIB Visual Studio workspace supports the building of PJLIB
* for Win32 target. Although currently only the Visual Studio 6 Workspace is
* actively maintained, developers with later version of Visual Studio
* can easily imports VS6 workspace into their IDE.
*
* To start building PJLIB projects with Visual Studio 6 or later, open
* the \a workspace file in the corresponding \b \c build directory. You have
* several choices on which \a dsw file to open:
\verbatim
$PJPROJECT/pjlib/build/pjlib.dsw
$PJPROJECT/pjsip/build/pjsip.dsw
..etc
\endverbatim
*
* The easiest way is to open <tt>pjsip_apps.dsw</tt> file in \b \c $PJPROJECT/pjsip-apps/build
* directory, and build pjsua project or the samples project.
* However this will not build the complete projects.
* For example, the PJLIB test is not included in this workspace.
* To build the complete projects, you must
* open and build each \a dsw file in \c build directory in each
* subprojects. For example, to open the complete PJLIB workspace, open
* <tt>pjlib.dsw</tt> in <tt>$PJPROJECT/pjlib/build</tt> directory.
*
*
* @subsubsection config_site_create_vc_sec Create config_site.h
*
* The file <tt><b>$PJPROJECT/pjlib/include/pj/config_site.h</b></tt>
* is supposed to contain configuration that is specific to your site/target.
* This file is not part of PJLIB, so you must create it yourself. Normally
* you just need to create a blank file.
*
* The reason why it's not included in PJLIB is so that you would not accidently
* overwrite your site configuration.
*
* If you fail to do this, Visual C will complain with error like:
*
* <b>"fatal error C1083: Cannot open include file: 'pj/config_site.h': No such file
* or directory"</b>.
*
* @subsubsection build_vc_subsubsec Build the Projects
*
* Just hit the build button!
*
*
* @subsection build_sys_install_unix_sec Make System
*
* For other targets, PJLIB provides a rather comprehensive build system
* that uses GNU \a make (and only GNU \a make will work).
* Currently, the build system supports building * PJLIB for these targets:
* - i386/Win32/mingw
* - i386/Linux
* - i386/Linux (kernel)
* - alpha/linux
* - sparc/SunOS
* - etc..
*
*
* @subsubsection build_req_sec Requirements
*
* In order to use the \c make based build system, you MUST have:
*
* - <b>GNU make</b>
*\n
* The Makefiles heavily utilize GNU make commands which most likely
* are not available in other \c make system.
* - <b>bash</b> shell is recommended.
*\n
* Specificly, there is a command <tt>"echo -n"</tt> which may not work
* in other shells. This command is used when generating dependencies
* (<tt>make dep</tt>) and it's located in
* <tt>$PJPROJECT/build/rules.mak</tt>.
* - <b>ar</b>, <b>ranlib</b> from GNU binutils
*\n
* In your system has different <tt>ar</tt> or <tt>ranlib</tt> (e.g. they
* may have been installed as <tt>gar</tt> and <tt>granlib</tt>), then
* either you create the relevant symbolic links, <b>or</b> modify
* <tt>$PJPROJECT/build/cc-gcc.mak</tt> and rename <tt>ar</tt> and
* <tt>ranlib</tt> to the appropriate names.
* - <b>gcc</b> to generate dependency.
*\n
* Currently the build system uses <tt>"gcc -MM"</tt> to generate build
* dependencies. If <tt>gcc</tt> is not desired to generate dependency,
* then either you don't run <tt>make dep</tt>, <b>or</b> edit
* <tt>$PJPROJECT/build/rules.mak</tt> to calculate dependency using
* your prefered method. (And let me know when you do so so that I can
* update the file. :) )
*
* @subsubsection build_overview_sec Building the Project
*
* Generally, steps required to build the PJLIB are:
*
\verbatim
$ cd /home/user/pjproject
$ ./configure
$ touch pjlib/include/pj/config_site.h
$ make dep
$ make
\endverbatim
*
* The above process will build all static libraries and all applications.
*
* \note the <tt>configure</tt> script is not a proper autoconf script,
* but rather a simple shell script to detect current host. This script
* currently does not support cross-compilation.
*
* \note For Linux kernel target, there are additional steps required, which
* will be explained in section \ref linux_kern_target_subsec.
*
* @subsubsection build_mak_sec Cross Compilation
*
* For cross compilation, you will need to edit the \c build.mak file in
* \c $PJPROJECT root directory manually. Please see <b>README-configure</b> file
* in the root directory for more information.
*
* For Linux kernel target, you are also required to declare the following
* variables in this file:
* - \c KERNEL_DIR: full path of kernel source tree.
* - \c KERNEL_ARCH: kernel ARCH options (e.g. "ARCH=um"), or leave blank
* for default.
* - \c PJPROJECT_DIR: full path of PJPROJECT source tree.
*
* Apart from these, there are also additional steps required to build
* Linux kernel target, which will be explained in \ref linux_kern_target_subsec.
*
* @subsubsection build_dir_sec Files in "build" Directory
*
* The <tt>*.mak</tt> files in \c $PJPROJECT/build directory are used to specify
* the configuration for the specified compiler, target machine target
* operating system, and host options. These files will be executed
* (included) by \a make during building process, depending on the values
* specified in <b>$PJPROJECT/build.mak</b> file.
*
* Normally you don't need to edit these files, except when you're porting
* PJLIB to new target.
*
* Below are the description of some files in this directory:
*
* - <tt>rules.mak</tt>: contains generic rules always included during make.
* - <tt>cc-gcc.mak</tt>: rules when gcc is used for compiler.
* - <tt>cc-vc.mak</tt>: rules when MSVC compiler is used.
* - <tt>host-mingw.mak</tt>: rules for building in mingw host.
* - <tt>host-unix.mak</tt>: rules for building in Unix/Posix host.
* - <tt>host-win32.mak</tt>: rules for building in Win32 command console
* (only valid when VC is used).
* - <tt>m-i386.mak</tt>: rules when target machine is an i386 processor.
* - <tt>m-m68k.mak</tt>: rules when target machine is an m68k processor.
* - <tt>os-linux.mak</tt>: rules when target OS is Linux.
* - <tt>os-linux-kernel.mak</tt>: rules when PJLIB is to be build as
* part of Linux kernel.
* - <tt>os-win32.mak</tt>: rules when target OS is Win32.
*
*
* @subsubsection config_site_create_sec Create config_site.h
*
* The file <tt><b>$PJPROJECT/pjlib/include/pj/config_site.h</b></tt>
* is supposed to contain configuration that is specific to your site/target.
* This file is not part of PJLIB, so you must create it yourself.
*
* The reason why it's not included in PJLIB is so that you would not accidently
* overwrite your site configuration.
*
*
* @subsubsection invoking_make_sec Invoking make
*
* Normally, \a make is invoked in \c build directory under each project.
* For example, to build PJLIB, you would invoke \a make in
* \c $PJPROJECT/pjlib/build directory like below:
*
\verbatim
$ cd pjlib/build
$ make
\endverbatim
*
* Alternatively you may invoke <tt>make</tt> in <tt>$PJPROJECT</tt>
* directory, to build all projects under that directory (e.g.
* PJLIB, PJSIP, etc.).
*
*
* @subsubsection linux_kern_target_subsec Linux Kernel Target
*
* \note
* <b>BUILDING APPLICATIONS IN LINUX KERNEL MODE IS A VERY DANGEROUS BUSINESS.
* YOU MAY CRASH THE WHOLE OF YOUR SYSTEM, CORRUPT YOUR HARDISK, ETC. PJLIB
* KERNEL MODULES ARE STILL IN EXPERIMENTAL PHASE. DO NOT RUN IT IN PRODUCTION
* SYSTEMS OR OTHER SYSTEMS WHERE RISK OF LOSS OF DATA IS NOT ACCEPTABLE.
* YOU HAVE BEEN WARNED.</b>
*
* \note
* <b>User Mode Linux (UML)</b> provides excellent way to experiment with Linux
* kernel without risking the stability of the host system. See
* http://user-mode-linux.sourceforge.net for details.
*
* \note
* I only use <b>UML</b> to experiment with PJLIB kernel modules.
* <b>I wouldn't be so foolish to use my host Linux machine to experiment
* with this.</b>
*
* \note
* You have been warned.
*
* For building PJLIB for Linux kernel target, there are additional steps required.
* In general, the additional tasks are:
* - Declare some more variables in <b><tt>build.mak</tt></b> file (this
* has been explained in \ref build_mak_sec above).
* - Perform these two small modifications in kernel source tree.
*
* There are two small modification need to be applied to the kernel tree.
*
* <b>1. Edit <tt>Makefile</tt> in kernel root source tree.</b>
*
* Add the following lines at the end of the <tt>Makefile</tt> in your
* <tt>$KERNEL_SRC</tt> dir:
\verbatim
script:
$(SCRIPT)
\endverbatim
*
* \note Remember to replace spaces with <b>tab</b> in the Makefile.
*
* The modification above is needed to capture kernel's \c $CFLAGS and
* \c $CFLAGS_MODULE which will be used for PJLIB's compilation.
*
* <b>2. Add Additional Exports.</b>
*
* We need the kernel to export some more symbols for our use. So we declare
* the additional symbols to be exported in <tt>extra-exports.c</tt> file, and add
* a this file to be compiled into the kernel:
*
* - Copy the file <tt>extra-exports.c</tt> from <tt>pjlib/src/pj</tt>
* directory to <tt>$KERNEL_SRC/kernel/</tt> directory.
* - Edit <tt>Makefile</tt> in that directory, and add this line
* somewhere after the declaration of that variable:
\verbatim
obj-y += extra-exports.o
\endverbatim
*
* To illustrate what have been done in your kernel source tree, below
* is screenshot of my kernel source tree _after_ the modification.
*
\verbatim
[root@vpc-linux linux-2.6.7]# pwd
/usr/src/linux-2.6.7
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]# tail Makefile
endif # skip-makefile
FORCE:
.PHONY: script
script:
$(SCRIPT)
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]# head kernel/extra-exports.c
#include <linux/module.h>
#include <linux/syscalls.h>
EXPORT_SYMBOL(sys_select);
EXPORT_SYMBOL(sys_epoll_create);
EXPORT_SYMBOL(sys_epoll_ctl);
EXPORT_SYMBOL(sys_epoll_wait);
EXPORT_SYMBOL(sys_socket);
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]# head -15 kernel/Makefile
#
# Makefile for the linux kernel.
#
obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
exit.o itimer.o time.o softirq.o resource.o \
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o intermodule.o extable.o params.o posix-timers.o \
kthread.o
obj-y += extra-exports.o
obj-$(CONFIG_FUTEX) += futex.o
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
[root@vpc-linux linux-2.6.7]#
\endverbatim
*
* Then you must rebuild the kernel.
* If you fail to do this, you won't be able to <b>insmod</b> pjlib.
*
* \note You will see a lots of warning messages during pjlib-test compilation.
* The warning messages complain about unresolved symbols which are defined
* in pjlib module. You can safely ignore these warnings. However, you can not
* ignore warnings about non-pjlib unresolved symbols.
*
*
* @subsection makefile_explained_sec Makefile Explained
*
* The \a Makefile for each project (e.g. PJLIB, PJSIP, etc) should be
* very similar in the contents. The Makefile is located under \c build
* directory in each project subdir.
*
* @subsubsection pjlib_makefile_subsec PJLIB Makefile.
*
* Below is PJLIB's Makefile:
*
* \include build/Makefile
*
* @subsubsection pjlib_os_makefile_subsec PJLIB os-linux.mak.
*
* Below is file <tt><b>os-linux.mak</b></tt> file in
* <tt>$PJPROJECT/pjlib/build</tt> directory,
* which is OS specific configuration file for Linux target that is specific
* for PJLIB project. For \b global OS specific configuration, please see
* <tt>$PJPROJECT/build/os-*.mak</tt>.
*
* \include build/os-linux.mak
*
*/
/*////////////////////////////////////////////////////////////////////////// */
/*
PORTING PJLIB
*/
/**
* @page porting_pjlib_pg Porting PJLIB
*
* \note
* <b>Since version 0.5.8, PJLIB build system is now based on autoconf, so
* most of the time we shouldn't need to apply the tweakings below to get
* PJLIB working on a new platform. However, since the autoconf build system
* still uses the old Makefile build system, the information below may still
* be useful for reference.
* </b>
*
* @section new_arch_sec Porting to New CPU Architecture
*
* Below is step-by-step guide to add support for new CPU architecture.
* This sample is based on porting to Alpha architecture; however steps for
* porting to other CPU architectures should be pretty similar.
*
* Also note that in this example, the operating system used is <b>Linux</b>.
* Should you wish to add support for new operating system, then follow
* the next section \ref porting_os_sec.
*
* Step-by-step guide to port to new CPU architecture:
* - decide the name for the new architecture. In this case, we choose
* <tt><b>alpha</b></tt>.
* - edit file <tt>$PJPROJECT/build.mak</tt>, and add new section for
* the new target:
* <pre>
* #
* # Linux alpha, gcc
* #
* export MACHINE_NAME := <b>alpha</b>
* export OS_NAME := linux
* export CC_NAME := gcc
* export HOST_NAME := unix
* </pre>
*
* - create a new file <tt>$PJPROJECT/build/<b>m-alpha</b>.mak</tt>.
* Alternatively create a copy from other file in this directory.
* The contents of this file will look something like:
* <pre>
* export M_CFLAGS := $(CC_DEF)<b>PJ_M_ALPHA=1</b>
* export M_CXXFLAGS :=
* export M_LDFLAGS :=
* export M_SOURCES :=
* </pre>
* - create a new file <tt>$PJPROJECT/pjlib/include/pj/compat/<b>m_alpha.h</b></tt>.
* Alternatively create a copy from other header file in this directory.
* The contents of this file will look something like:
* <pre>
* #define PJ_HAS_PENTIUM 0
* #define PJ_IS_LITTLE_ENDIAN 1
* #define PJ_IS_BIG_ENDIAN 0
* </pre>
* - edit <tt>pjlib/include/pj/<b>config.h</b></tt>. Add new processor
* configuration in this header file, like follows:
* <pre>
* ...
* #elif defined (PJ_M_ALPHA) && PJ_M_ALPHA != 0
* # include <pj/compat/m_alpha.h>
* ...
* </pre>
* - done. Build PJLIB with:
* <pre>
* $ cd $PJPROJECT/pjlib/build
* $ make dep
* $ make clean
* $ make
* </pre>
*
* @section porting_os_sec Porting to New Operating System Target
*
* This section will try to give you rough guideline on how to
* port PJLIB to a new target. As a sample, we give the target a name tag,
* for example <tt><b>xos</b></tt> (for X OS).
*
* @subsection new_compat_os_h_file_sec Create New Compat Header File
*
* You'll need to create a new header file
* <b><tt>include/pj/compat/os_xos.h</tt></b>. You can copy as a
* template other header file and edit it accordingly.
*
* @subsection modify_config_h_file_sec Modify config.h
*
* Then modify file <b><tt>include/pj/config.h</tt></b> to include
* this file accordingly (e.g. when macro <tt><b>PJ_XOS</b></tt> is
* defined):
*
\verbatim
...
#elif defined(PJ_XOS)
# include <pj/compat/os_xos.h>
#else
#...
\endverbatim
*
* @subsection new_target_mak_file_sec Create New Global Make Config File
*
* Then you'll need to create global configuration file that
* is specific for this OS, i.e. <tt><b>os-xos.mak</b></tt> in
* <tt><b>$PJPROJECT/build</b></tt> directory.
*
* At very minimum, the file will normally need to define
* <tt><b>PJ_XOS=1</b></tt> in the \c CFLAGS section:
*
\verbatim
#
# $PJPROJECT/build/os-xos.mak:
#
export OS_CFLAGS := $(CC_DEF)PJ_XOS=1
export OS_CXXFLAGS :=
export OS_LDFLAGS :=
export OS_SOURCES :=
\endverbatim
*
*
* @subsection new_target_prj_mak_file_sec Create New Project's Make Config File
*
* Then you'll need to create xos-specific configuration file
* for PJLIB. This file is also named <tt><b>os-xos.mak</b></tt>,
* but its located in <tt><b>pjlib/build</b></tt> directory.
* This file will specify source files that are specific to
* this OS to be included in the build process.
*
* Below is a sample:
\verbatim
#
# pjlib/build/os-xos.mak:
# XOS specific configuration for PJLIB.
#
export PJLIB_OBJS += os_core_xos.o \
os_error_unix.o \
os_time_ansi.o
export TEST_OBJS += main.o
export TARGETS = pjlib pjlib-test
\endverbatim
*
* @subsection new_target_src_sec Create and Edit Source Files
*
* You'll normally need to create at least these files:
* - <tt><b>os_core_xos.c</b></tt>: core OS specific
* functionality.
* - <tt><b>os_timestamp_xos.c</b></tt>: how to get timestamp
* in this OS.
*
* Depending on how things are done in your OS, you may need
* to create these files:
* - <tt><b>os_error_*.c</b></tt>: how to manipulate
* OS error codes. Alternatively you may use existing
* <tt>os_error_unix.c</tt> if the OS has \c errno and
* \c strerror() function.
* - <tt><b>ioqueue_*.c</b></tt>: if the OS has specific method
* to perform asynchronous I/O. Alternatively you may
* use existing <tt>ioqueue_select.c</tt> if the OS supports
* \c select() function call.
* - <tt><b>sock_*.c</b></tt>: if the OS has specific method
* to perform socket communication. Alternatively you may
* use existing <tt>sock_bsd.c</tt> if the OS supports
* BSD socket API, and edit <tt>include/pj/compat/socket.h</tt>
* file accordingly.
*
* You will also need to check various files in
* <tt><b>include/pj/compat/xxx.h</b></tt>, to see if they're
* compatible with your OS.
*
* @subsection new_target_build_file_sec Build The Project
*
* After basic building blocks have been created for the OS, then
* the easiest way to see which parts need to be fixed is by building
* the project and see the error messages.
*
* @subsection new_target_edit_vs_new_file_sec Editing Existing Files vs Creating New File
*
* When you encounter compatibility errors in PJLIB during porting,
* you have three options on how to fix the error:
* - edit the existing <tt>*.c</tt> file, and give it <tt>#ifdef</tt>
* switch for the new OS, or
* - edit <tt>include/pj/compat/*.h</tt> instead, or
* - create a totally new file.
*
* Basicly there is no strict rule on which approach is the best
* to use, however the following guidelines may be used:
* - if the file is expected to be completely different than
* any existing file, then perhaps you should create a completely
* new file. For example, file <tt>os_core_xxx.c</tt> will
* normally be different for each OS flavour.
* - if the difference can be localized in <tt>include/compat</tt>
* header file, and existing <tt>#ifdef</tt> switch is there,
* then preferably you should edit this <tt>include/compat</tt>
* header file.
* - if the existing <tt>*.c</tt> file has <tt>#ifdef</tt> switch,
* then you may add another <tt>#elif</tt> switch there. This
* normally is used for behaviors that are not totally
* different on each platform.
* - other than that above, use your own judgement on whether
* to edit the file or create new file etc.
*/
#endif /* __PJ_DOXYGEN_H__ */

View File

@@ -0,0 +1,593 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_ERRNO_H__
#define __PJ_ERRNO_H__
/**
* @file errno.h
* @brief PJLIB Error Subsystem
*/
#include <pj/types.h>
#include <pj/compat/errno.h>
#include <stdarg.h>
PJ_BEGIN_DECL
/**
* @defgroup pj_errno Error Subsystem
* @{
*
* The PJLIB Error Subsystem is a framework to unify all error codes
* produced by all components into a single error space, and provide
* uniform set of APIs to access them. With this framework, any error
* codes are encoded as pj_status_t value. The framework is extensible,
* application may register new error spaces to be recognized by
* the framework.
*
* @section pj_errno_retval Return Values
*
* All functions that returns @a pj_status_t returns @a PJ_SUCCESS if the
* operation was completed successfully, or non-zero value to indicate
* error. If the error came from operating system, then the native error
* code is translated/folded into PJLIB's error namespace by using
* #PJ_STATUS_FROM_OS() macro. The function will do this automatically
* before returning the error to caller.
*
* @section err_services Retrieving and Displaying Error Messages
*
* The framework provides the following APIs to retrieve and/or display
* error messages:
*
* - #pj_strerror(): this is the base API to retrieve error string
* description for the specified pj_status_t error code.
*
* - #PJ_PERROR() macro: use this macro similar to PJ_LOG to format
* an error message and display them to the log
*
* - #pj_perror(): this function is similar to PJ_PERROR() but unlike
* #PJ_PERROR(), this function will always be included in the
* link process. Due to this reason, prefer to use #PJ_PERROR()
* if the application is concerned about the executable size.
*
* Application MUST NOT pass native error codes (such as error code from
* functions like GetLastError() or errno) to PJLIB functions expecting
* @a pj_status_t.
*
* @section err_extending Extending the Error Space
*
* Application may register new error space to be recognized by the
* framework by using #pj_register_strerror(). Use the range started
* from PJ_ERRNO_START_USER to avoid conflict with existing error
* spaces.
*
*/
/**
* Guidelines on error message length.
*/
#define PJ_ERR_MSG_SIZE 80
/**
* Buffer for title string of #PJ_PERROR().
*/
#ifndef PJ_PERROR_TITLE_BUF_SIZE
# define PJ_PERROR_TITLE_BUF_SIZE 120
#endif
/**
* Get the last platform error/status, folded into pj_status_t.
* @return OS dependent error code, folded into pj_status_t.
* @remark This function gets errno, or calls GetLastError() function and
* convert the code into pj_status_t with PJ_STATUS_FROM_OS. Do
* not call this for socket functions!
* @see pj_get_netos_error()
*/
PJ_DECL(pj_status_t) pj_get_os_error(void);
/**
* Set last error.
* @param code pj_status_t
*/
PJ_DECL(void) pj_set_os_error(pj_status_t code);
/**
* Get the last error from socket operations.
* @return Last socket error, folded into pj_status_t.
*/
PJ_DECL(pj_status_t) pj_get_netos_error(void);
/**
* Set error code.
* @param code pj_status_t.
*/
PJ_DECL(void) pj_set_netos_error(pj_status_t code);
/**
* Get the error message for the specified error code. The message
* string will be NULL terminated.
*
* @param statcode The error code.
* @param buf Buffer to hold the error message string.
* @param bufsize Size of the buffer.
*
* @return The error message as NULL terminated string,
* wrapped with pj_str_t.
*/
PJ_DECL(pj_str_t) pj_strerror( pj_status_t statcode,
char *buf, pj_size_t bufsize);
/**
* A utility macro to print error message pertaining to the specified error
* code to the log. This macro will construct the error message title
* according to the 'title_fmt' argument, and add the error string pertaining
* to the error code after the title string. A colon (':') will be added
* automatically between the title and the error string.
*
* This function is similar to pj_perror() function, but has the advantage
* that the function call can be omitted from the link process if the
* log level argument is below PJ_LOG_MAX_LEVEL threshold.
*
* Note that the title string constructed from the title_fmt will be built on
* a string buffer which size is PJ_PERROR_TITLE_BUF_SIZE, which normally is
* allocated from the stack. By default this buffer size is small (around
* 120 characters). Application MUST ensure that the constructed title string
* will not exceed this limit, since not all platforms support truncating
* the string.
*
* @see pj_perror()
*
* @param level The logging verbosity level, valid values are 0-6. Lower
* number indicates higher importance, with level zero
* indicates fatal error. Only numeral argument is
* permitted (e.g. not variable).
* @param arg Enclosed 'printf' like arguments, with the following
* arguments:
* - the sender (NULL terminated string),
* - the error code (pj_status_t)
* - the format string (title_fmt), and
* - optional variable number of arguments suitable for the
* format string.
*
* Sample:
* \verbatim
PJ_PERROR(2, (__FILE__, PJ_EBUSY, "Error making %s", "coffee"));
\endverbatim
* @hideinitializer
*/
#define PJ_PERROR(level,arg) do { \
pj_perror_wrapper_##level(arg); \
} while (0)
/**
* A utility function to print error message pertaining to the specified error
* code to the log. This function will construct the error message title
* according to the 'title_fmt' argument, and add the error string pertaining
* to the error code after the title string. A colon (':') will be added
* automatically between the title and the error string.
*
* Unlike the PJ_PERROR() macro, this function takes the \a log_level argument
* as a normal argument, unlike in PJ_PERROR() where a numeral value must be
* given. However this function will always be linked to the executable,
* unlike PJ_PERROR() which can be omitted when the level is below the
* PJ_LOG_MAX_LEVEL.
*
* Note that the title string constructed from the title_fmt will be built on
* a string buffer which size is PJ_PERROR_TITLE_BUF_SIZE, which normally is
* allocated from the stack. By default this buffer size is small (around
* 120 characters). Application MUST ensure that the constructed title string
* will not exceed this limit, since not all platforms support truncating
* the string.
*
* @see PJ_PERROR()
*/
PJ_DECL(void) pj_perror(int log_level, const char *sender, pj_status_t status,
const char *title_fmt, ...)
PJ_PRINT_FUNC_DECOR(4);
/**
* Type of callback to be specified in #pj_register_strerror()
*
* @param e The error code to lookup.
* @param msg Buffer to store the error message.
* @param max Length of the buffer.
*
* @return The error string.
*/
typedef pj_str_t (*pj_error_callback)(pj_status_t e, char *msg, pj_size_t max);
/**
* Register strerror message handler for the specified error space.
* Application can register its own handler to supply the error message
* for the specified error code range. This handler will be called
* by #pj_strerror().
*
* @param start_code The starting error code where the handler should
* be called to retrieve the error message.
* @param err_space The size of error space. The error code range then
* will fall in start_code to start_code+err_space-1
* range.
* @param f The handler to be called when #pj_strerror() is
* supplied with error code that falls into this range.
*
* @return PJ_SUCCESS or the specified error code. The
* registration may fail when the error space has been
* occupied by other handler, or when there are too many
* handlers registered to PJLIB.
*/
PJ_DECL(pj_status_t) pj_register_strerror(pj_status_t start_code,
pj_status_t err_space,
pj_error_callback f);
/**
* @hideinitializer
* Return platform os error code folded into pj_status_t code. This is
* the macro that is used throughout the library for all PJLIB's functions
* that returns error from operating system. Application may override
* this macro to reduce size (e.g. by defining it to always return
* #PJ_EUNKNOWN).
*
* Note:
* This macro MUST return non-zero value regardless whether zero is
* passed as the argument. The reason is to protect logic error when
* the operating system doesn't report error codes properly.
*
* @param os_code Platform OS error code. This value may be evaluated
* more than once.
* @return The platform os error code folded into pj_status_t.
*/
#ifndef PJ_RETURN_OS_ERROR
# define PJ_RETURN_OS_ERROR(os_code) (os_code ? \
PJ_STATUS_FROM_OS(os_code) : -1)
#endif
/**
* @hideinitializer
* Fold a platform specific error into an pj_status_t code.
*
* @param e The platform os error code.
* @return pj_status_t
* @warning Macro implementation; the syserr argument may be evaluated
* multiple times.
*/
#if PJ_NATIVE_ERR_POSITIVE
# define PJ_STATUS_FROM_OS(e) (e == 0 ? PJ_SUCCESS : e + PJ_ERRNO_START_SYS)
#else
# define PJ_STATUS_FROM_OS(e) (e == 0 ? PJ_SUCCESS : PJ_ERRNO_START_SYS - e)
#endif
/**
* @hideinitializer
* Fold an pj_status_t code back to the native platform defined error.
*
* @param e The pj_status_t folded platform os error code.
* @return pj_os_err_type
* @warning macro implementation; the statcode argument may be evaluated
* multiple times. If the statcode was not created by
* pj_get_os_error or PJ_STATUS_FROM_OS, the results are undefined.
*/
#if PJ_NATIVE_ERR_POSITIVE
# define PJ_STATUS_TO_OS(e) (e == 0 ? PJ_SUCCESS : e - PJ_ERRNO_START_SYS)
#else
# define PJ_STATUS_TO_OS(e) (e == 0 ? PJ_SUCCESS : PJ_ERRNO_START_SYS - e)
#endif
/**
* @defgroup pj_errnum PJLIB's Own Error Codes
* @ingroup pj_errno
* @{
*/
/**
* Use this macro to generate error message text for your error code,
* so that they look uniformly as the rest of the libraries.
*
* @param code The error code
* @param msg The error test.
*/
#ifndef PJ_BUILD_ERR
# define PJ_BUILD_ERR(code,msg) { code, msg " (" #code ")" }
#endif
/**
* @hideinitializer
* Unknown error has been reported.
*/
#define PJ_EUNKNOWN (PJ_ERRNO_START_STATUS + 1) /* 70001 */
/**
* @hideinitializer
* The operation is pending and will be completed later.
*/
#define PJ_EPENDING (PJ_ERRNO_START_STATUS + 2) /* 70002 */
/**
* @hideinitializer
* Too many connecting sockets.
*/
#define PJ_ETOOMANYCONN (PJ_ERRNO_START_STATUS + 3) /* 70003 */
/**
* @hideinitializer
* Invalid argument.
*/
#define PJ_EINVAL (PJ_ERRNO_START_STATUS + 4) /* 70004 */
/**
* @hideinitializer
* Name too long (eg. hostname too long).
*/
#define PJ_ENAMETOOLONG (PJ_ERRNO_START_STATUS + 5) /* 70005 */
/**
* @hideinitializer
* Not found.
*/
#define PJ_ENOTFOUND (PJ_ERRNO_START_STATUS + 6) /* 70006 */
/**
* @hideinitializer
* Not enough memory.
*/
#define PJ_ENOMEM (PJ_ERRNO_START_STATUS + 7) /* 70007 */
/**
* @hideinitializer
* Bug detected!
*/
#define PJ_EBUG (PJ_ERRNO_START_STATUS + 8) /* 70008 */
/**
* @hideinitializer
* Operation timed out.
*/
#define PJ_ETIMEDOUT (PJ_ERRNO_START_STATUS + 9) /* 70009 */
/**
* @hideinitializer
* Too many objects.
*/
#define PJ_ETOOMANY (PJ_ERRNO_START_STATUS + 10)/* 70010 */
/**
* @hideinitializer
* Object is busy.
*/
#define PJ_EBUSY (PJ_ERRNO_START_STATUS + 11)/* 70011 */
/**
* @hideinitializer
* The specified option is not supported.
*/
#define PJ_ENOTSUP (PJ_ERRNO_START_STATUS + 12)/* 70012 */
/**
* @hideinitializer
* Invalid operation.
*/
#define PJ_EINVALIDOP (PJ_ERRNO_START_STATUS + 13)/* 70013 */
/**
* @hideinitializer
* Operation is cancelled.
*/
#define PJ_ECANCELLED (PJ_ERRNO_START_STATUS + 14)/* 70014 */
/**
* @hideinitializer
* Object already exists.
*/
#define PJ_EEXISTS (PJ_ERRNO_START_STATUS + 15)/* 70015 */
/**
* @hideinitializer
* End of file.
*/
#define PJ_EEOF (PJ_ERRNO_START_STATUS + 16)/* 70016 */
/**
* @hideinitializer
* Size is too big.
*/
#define PJ_ETOOBIG (PJ_ERRNO_START_STATUS + 17)/* 70017 */
/**
* @hideinitializer
* Error in gethostbyname(). This is a generic error returned when
* gethostbyname() has returned an error.
*/
#define PJ_ERESOLVE (PJ_ERRNO_START_STATUS + 18)/* 70018 */
/**
* @hideinitializer
* Size is too small.
*/
#define PJ_ETOOSMALL (PJ_ERRNO_START_STATUS + 19)/* 70019 */
/**
* @hideinitializer
* Ignored
*/
#define PJ_EIGNORED (PJ_ERRNO_START_STATUS + 20)/* 70020 */
/**
* @hideinitializer
* IPv6 is not supported
*/
#define PJ_EIPV6NOTSUP (PJ_ERRNO_START_STATUS + 21)/* 70021 */
/**
* @hideinitializer
* Unsupported address family
*/
#define PJ_EAFNOTSUP (PJ_ERRNO_START_STATUS + 22)/* 70022 */
/**
* @hideinitializer
* Object no longer exists
*/
#define PJ_EGONE (PJ_ERRNO_START_STATUS + 23)/* 70023 */
/**
* @hideinitializer
* Socket is stopped
*/
#define PJ_ESOCKETSTOP (PJ_ERRNO_START_STATUS + 24)/* 70024 */
/** @} */ /* pj_errnum */
/** @} */ /* pj_errno */
/**
* PJ_ERRNO_START is where PJLIB specific error values start.
*/
#define PJ_ERRNO_START 20000
/**
* PJ_ERRNO_SPACE_SIZE is the maximum number of errors in one of
* the error/status range below.
*/
#define PJ_ERRNO_SPACE_SIZE 50000
/**
* PJ_ERRNO_START_STATUS is where PJLIB specific status codes start.
* Effectively the error in this class would be 70000 - 119000.
*/
#define PJ_ERRNO_START_STATUS (PJ_ERRNO_START + PJ_ERRNO_SPACE_SIZE)
/**
* PJ_ERRNO_START_SYS converts platform specific error codes into
* pj_status_t values.
* Effectively the error in this class would be 120000 - 169000.
*/
#define PJ_ERRNO_START_SYS (PJ_ERRNO_START_STATUS + PJ_ERRNO_SPACE_SIZE)
/**
* PJ_ERRNO_START_USER are reserved for applications that use error
* codes along with PJLIB codes.
* Effectively the error in this class would be 170000 - 219000.
*/
#define PJ_ERRNO_START_USER (PJ_ERRNO_START_SYS + PJ_ERRNO_SPACE_SIZE)
/*
* Below are list of error spaces that have been taken so far:
* - PJSIP_ERRNO_START (PJ_ERRNO_START_USER)
* - PJMEDIA_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE)
* - PJSIP_SIMPLE_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*2)
* - PJLIB_UTIL_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*3)
* - PJNATH_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*4)
* - PJMEDIA_AUDIODEV_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*5)
* - PJ_SSL_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*6)
* - PJMEDIA_VIDEODEV_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*7)
*/
/** Internal */
void pj_errno_clear_handlers(void);
/****** Internal for PJ_PERROR *******/
/**
* @def pj_perror_wrapper_1(arg)
* Internal function to write log with verbosity 1. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 1.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 1
#define pj_perror_wrapper_1(arg) pj_perror_1 arg
/** Internal function. */
PJ_DECL(void) pj_perror_1(const char *sender, pj_status_t status,
const char *title_fmt, ...)
PJ_PRINT_FUNC_DECOR(3);
#else
#define pj_perror_wrapper_1(arg)
#endif
/**
* @def pj_perror_wrapper_2(arg)
* Internal function to write log with verbosity 2. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 2.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 2
#define pj_perror_wrapper_2(arg) pj_perror_2 arg
/** Internal function. */
PJ_DECL(void) pj_perror_2(const char *sender, pj_status_t status,
const char *title_fmt, ...)
PJ_PRINT_FUNC_DECOR(3);
#else
#define pj_perror_wrapper_2(arg)
#endif
/**
* @def pj_perror_wrapper_3(arg)
* Internal function to write log with verbosity 3. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 3.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 3
#define pj_perror_wrapper_3(arg) pj_perror_3 arg
/** Internal function. */
PJ_DECL(void) pj_perror_3(const char *sender, pj_status_t status,
const char *title_fmt, ...)
PJ_PRINT_FUNC_DECOR(3);
#else
#define pj_perror_wrapper_3(arg)
#endif
/**
* @def pj_perror_wrapper_4(arg)
* Internal function to write log with verbosity 4. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 4.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 4
#define pj_perror_wrapper_4(arg) pj_perror_4 arg
/** Internal function. */
PJ_DECL(void) pj_perror_4(const char *sender, pj_status_t status,
const char *title_fmt, ...)
PJ_PRINT_FUNC_DECOR(3);
#else
#define pj_perror_wrapper_4(arg)
#endif
/**
* @def pj_perror_wrapper_5(arg)
* Internal function to write log with verbosity 5. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 5.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 5
#define pj_perror_wrapper_5(arg) pj_perror_5 arg
/** Internal function. */
PJ_DECL(void) pj_perror_5(const char *sender, pj_status_t status,
const char *title_fmt, ...)
PJ_PRINT_FUNC_DECOR(3);
#else
#define pj_perror_wrapper_5(arg)
#endif
/**
* @def pj_perror_wrapper_6(arg)
* Internal function to write log with verbosity 6. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 6.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 6
#define pj_perror_wrapper_6(arg) pj_perror_6 arg
/** Internal function. */
PJ_DECL(void) pj_perror_6(const char *sender, pj_status_t status,
const char *title_fmt, ...)
PJ_PRINT_FUNC_DECOR(3);
#else
#define pj_perror_wrapper_6(arg)
#endif
PJ_END_DECL
#endif /* __PJ_ERRNO_H__ */

View File

@@ -0,0 +1,420 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_EXCEPTION_H__
#define __PJ_EXCEPTION_H__
/**
* @file except.h
* @brief Exception Handling in C.
*/
#include <pj/types.h>
#include <pj/compat/setjmp.h>
#include <pj/log.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_EXCEPT Exception Handling
* @ingroup PJ_MISC
* @{
*
* \section pj_except_sample_sec Quick Example
*
* For the impatient, take a look at some examples:
* - Exception Handling sample: \src{pjlib/src/pjlib-samples/except.c}
* - Exception Handling test: \src{pjlib/src/pjlib-test/exception.c}
*
* \section pj_except_except Exception Handling
*
* This module provides exception handling syntactically similar to C++ in
* C language. In Win32 systems, it uses Windows Structured Exception
* Handling (SEH) if macro PJ_EXCEPTION_USE_WIN32_SEH is non-zero.
* Otherwise it will use setjmp() and longjmp().
*
* On some platforms where setjmp/longjmp is not available, setjmp/longjmp
* implementation is provided. See <pj/compat/setjmp.h> for compatibility.
*
* The exception handling mechanism is completely thread safe, so the exception
* thrown by one thread will not interfere with other thread.
*
* The exception handling constructs are similar to C++. The blocks will be
* constructed similar to the following sample:
*
* \verbatim
#define NO_MEMORY 1
#define SYNTAX_ERROR 2
int sample1()
{
PJ_USE_EXCEPTION; // declare local exception stack.
PJ_TRY {
...// do something..
}
PJ_CATCH(NO_MEMORY) {
... // handle exception 1
}
PJ_END;
}
int sample2()
{
PJ_USE_EXCEPTION; // declare local exception stack.
PJ_TRY {
...// do something..
}
PJ_CATCH_ANY {
if (PJ_GET_EXCEPTION() == NO_MEMORY)
...; // handle no memory situation
else if (PJ_GET_EXCEPTION() == SYNTAX_ERROR)
...; // handle syntax error
}
PJ_END;
}
\endverbatim
*
* The above sample uses hard coded exception ID. It is @b strongly
* recommended that applications request a unique exception ID instead
* of hard coded value like above.
*
* \section pj_except_reg Exception ID Allocation
*
* To ensure that exception ID (number) are used consistently and to
* prevent ID collisions in an application, it is strongly suggested that
* applications allocate an exception ID for each possible exception
* type. As a bonus of this process, the application can identify
* the name of the exception when the particular exception is thrown.
*
* Exception ID management are performed with the following APIs:
* - #pj_exception_id_alloc().
* - #pj_exception_id_free().
* - #pj_exception_id_name().
*
*
* PJLIB itself automatically allocates one exception id, i.e.
* #PJ_NO_MEMORY_EXCEPTION which is declared in <pj/pool.h>. This exception
* ID is raised by default pool policy when it fails to allocate memory.
*
* CAVEATS:
* - unlike C++ exception, the scheme here won't call destructors of local
* objects if exception is thrown. Care must be taken when a function
* hold some resorce such as pool or mutex etc.
* - You CAN NOT make nested exception in one single function without using
* a nested PJ_USE_EXCEPTION. Samples:
\verbatim
void wrong_sample()
{
PJ_USE_EXCEPTION;
PJ_TRY {
// Do stuffs
...
}
PJ_CATCH_ANY {
// Do other stuffs
....
..
// The following block is WRONG! You MUST declare
// PJ_USE_EXCEPTION once again in this block.
PJ_TRY {
..
}
PJ_CATCH_ANY {
..
}
PJ_END;
}
PJ_END;
}
\endverbatim
* - You MUST NOT exit the function inside the PJ_TRY block. The correct way
* is to return from the function after PJ_END block is executed.
* For example, the following code will yield crash not in this code,
* but rather in the subsequent execution of PJ_TRY block:
\verbatim
void wrong_sample()
{
PJ_USE_EXCEPTION;
PJ_TRY {
// do some stuffs
...
return; <======= DO NOT DO THIS!
}
PJ_CATCH_ANY {
}
PJ_END;
}
\endverbatim
* - You can not provide more than PJ_CATCH or PJ_CATCH_ANY nor use PJ_CATCH
* and PJ_CATCH_ANY for a single PJ_TRY.
* - Exceptions will always be caught by the first handler (unlike C++ where
* exception is only caught if the type matches.
* \section PJ_EX_KEYWORDS Keywords
*
* \subsection PJ_THROW PJ_THROW(expression)
* Throw an exception. The expression thrown is an integer as the result of
* the \a expression. This keyword can be specified anywhere within the
* program.
*
* \subsection PJ_USE_EXCEPTION PJ_USE_EXCEPTION
* Specify this in the variable definition section of the function block
* (or any blocks) to specify that the block has \a PJ_TRY/PJ_CATCH exception
* block.
* Actually, this is just a macro to declare local variable which is used to
* push the exception state to the exception stack.
* Note: you must specify PJ_USE_EXCEPTION as the last statement in the
* local variable declarations, since it may evaluate to nothing.
*
* \subsection PJ_TRY PJ_TRY
* The \a PJ_TRY keyword is typically followed by a block. If an exception is
* thrown in this block, then the execution will resume to the \a PJ_CATCH
* handler.
*
* \subsection PJ_CATCH PJ_CATCH(expression)
* The \a PJ_CATCH is normally followed by a block. This block will be executed
* if the exception being thrown is equal to the expression specified in the
* \a PJ_CATCH.
*
* \subsection PJ_CATCH_ANY PJ_CATCH_ANY
* The \a PJ_CATCH is normally followed by a block. This block will be executed
* if any exception was raised in the TRY block.
*
* \subsection PJ_END PJ_END
* Specify this keyword to mark the end of \a PJ_TRY / \a PJ_CATCH blocks.
*
* \subsection PJ_GET_EXCEPTION PJ_GET_EXCEPTION(void)
* Get the last exception thrown. This macro is normally called inside the
* \a PJ_CATCH or \a PJ_CATCH_ANY block, altough it can be used anywhere where
* the \a PJ_USE_EXCEPTION definition is in scope.
*
*
* \section pj_except_examples_sec Examples
*
* For some examples on how to use the exception construct, please see:
* - Exception Handling sample: \src{pjlib/src/pjlib-samples/except.c}
* - Exception Handling test: \src{pjlib/src/pjlib-test/exception.c}
*/
/**
* Allocate a unique exception id.
* Applications don't have to allocate a unique exception ID before using
* the exception construct. However, by doing so it ensures that there is
* no collisions of exception ID.
*
* As a bonus, when exception number is acquired through this function,
* the library can assign name to the exception (only if
* PJ_HAS_EXCEPTION_NAMES is enabled (default is yes)) and find out the
* exception name when it catches an exception.
*
* @param name Name to be associated with the exception ID.
* @param id Pointer to receive the ID.
*
* @return PJ_SUCCESS on success or PJ_ETOOMANY if the library
* is running out out ids.
*/
PJ_DECL(pj_status_t) pj_exception_id_alloc(const char *name,
pj_exception_id_t *id);
/**
* Free an exception id.
*
* @param id The exception ID.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_exception_id_free(pj_exception_id_t id);
/**
* Retrieve name associated with the exception id.
*
* @param id The exception ID.
*
* @return The name associated with the specified ID.
*/
PJ_DECL(const char*) pj_exception_id_name(pj_exception_id_t id);
/** @} */
#if defined(PJ_EXCEPTION_USE_WIN32_SEH) && PJ_EXCEPTION_USE_WIN32_SEH != 0
/*****************************************************************************
**
** IMPLEMENTATION OF EXCEPTION USING WINDOWS SEH
**
****************************************************************************/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
PJ_IDECL_NO_RETURN(void)
pj_throw_exception_(pj_exception_id_t id) PJ_ATTR_NORETURN
{
RaiseException(id,1,0,NULL);
}
#define PJ_USE_EXCEPTION
#define PJ_TRY __try
#define PJ_CATCH(id) __except(GetExceptionCode()==id ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH)
#define PJ_CATCH_ANY __except(EXCEPTION_EXECUTE_HANDLER)
#define PJ_END
#define PJ_THROW(id) pj_throw_exception_(id)
#define PJ_GET_EXCEPTION() GetExceptionCode()
#elif defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
/*****************************************************************************
**
** IMPLEMENTATION OF EXCEPTION USING SYMBIAN LEAVE/TRAP FRAMEWORK
**
****************************************************************************/
/* To include this file, the source file must be compiled as
* C++ code!
*/
#ifdef __cplusplus
class TPjException
{
public:
int code_;
};
#define PJ_USE_EXCEPTION
#define PJ_TRY try
//#define PJ_CATCH(id)
#define PJ_CATCH_ANY catch (const TPjException & pj_excp_)
#define PJ_END
#define PJ_THROW(x_id) do { TPjException e; e.code_=x_id; throw e;} \
while (0)
#define PJ_GET_EXCEPTION() pj_excp_.code_
#else
#define PJ_USE_EXCEPTION
#define PJ_TRY
#define PJ_CATCH_ANY if (0)
#define PJ_END
#define PJ_THROW(x_id) do { PJ_LOG(1,("PJ_THROW"," error code = %d",x_id)); } while (0)
#define PJ_GET_EXCEPTION() 0
#endif /* __cplusplus */
#else
/*****************************************************************************
**
** IMPLEMENTATION OF EXCEPTION USING GENERIC SETJMP/LONGJMP
**
****************************************************************************/
/**
* This structure (which should be invisible to user) manages the TRY handler
* stack.
*/
struct pj_exception_state_t
{
pj_jmp_buf state; /**< jmp_buf. */
struct pj_exception_state_t *prev; /**< Previous state in the list. */
};
/**
* Throw exception.
* @param id Exception Id.
*/
PJ_DECL_NO_RETURN(void)
pj_throw_exception_(pj_exception_id_t id) PJ_ATTR_NORETURN;
/**
* Push exception handler.
*/
PJ_DECL(void) pj_push_exception_handler_(struct pj_exception_state_t *rec);
/**
* Pop exception handler.
*/
PJ_DECL(void) pj_pop_exception_handler_(struct pj_exception_state_t *rec);
/**
* Declare that the function will use exception.
* @hideinitializer
*/
#define PJ_USE_EXCEPTION struct pj_exception_state_t pj_x_except__; int pj_x_code__
/**
* Start exception specification block.
* @hideinitializer
*/
#define PJ_TRY if (1) { \
pj_push_exception_handler_(&pj_x_except__); \
pj_x_code__ = pj_setjmp(pj_x_except__.state); \
if (pj_x_code__ == 0)
/**
* Catch the specified exception Id.
* @param id The exception number to catch.
* @hideinitializer
*/
#define PJ_CATCH(id) else if (pj_x_code__ == (id))
/**
* Catch any exception number.
* @hideinitializer
*/
#define PJ_CATCH_ANY else
/**
* End of exception specification block.
* @hideinitializer
*/
#define PJ_END pj_pop_exception_handler_(&pj_x_except__); \
} else {}
/**
* Throw exception.
* @param exception_id The exception number.
* @hideinitializer
*/
#define PJ_THROW(exception_id) pj_throw_exception_(exception_id)
/**
* Get current exception.
* @return Current exception code.
* @hideinitializer
*/
#define PJ_GET_EXCEPTION() (pj_x_code__)
#endif /* PJ_EXCEPTION_USE_WIN32_SEH */
PJ_END_DECL
#endif /* __PJ_EXCEPTION_H__ */

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_FIFOBUF_H__
#define __PJ_FIFOBUF_H__
#include <pj/types.h>
PJ_BEGIN_DECL
typedef struct pj_fifobuf_t pj_fifobuf_t;
struct pj_fifobuf_t
{
char *first, *last;
char *ubegin, *uend;
int full;
};
PJ_DECL(void) pj_fifobuf_init (pj_fifobuf_t *fb, void *buffer, unsigned size);
PJ_DECL(unsigned) pj_fifobuf_max_size (pj_fifobuf_t *fb);
PJ_DECL(void*) pj_fifobuf_alloc (pj_fifobuf_t *fb, unsigned size);
PJ_DECL(pj_status_t) pj_fifobuf_unalloc (pj_fifobuf_t *fb, void *buf);
PJ_DECL(pj_status_t) pj_fifobuf_free (pj_fifobuf_t *fb, void *buf);
PJ_END_DECL
#endif /* __PJ_FIFOBUF_H__ */

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_FILE_ACCESS_H__
#define __PJ_FILE_ACCESS_H__
/**
* @file file_access.h
* @brief File manipulation and access.
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_FILE_ACCESS File Access
* @ingroup PJ_IO
* @{
*
*/
/**
* This structure describes file information, to be obtained by
* calling #pj_file_getstat(). The time information in this structure
* is in local time.
*/
typedef struct pj_file_stat
{
pj_off_t size; /**< Total file size. */
pj_time_val atime; /**< Time of last access. */
pj_time_val mtime; /**< Time of last modification. */
pj_time_val ctime; /**< Time of last creation. */
} pj_file_stat;
/**
* Returns non-zero if the specified file exists.
*
* @param filename The file name.
*
* @return Non-zero if the file exists.
*/
PJ_DECL(pj_bool_t) pj_file_exists(const char *filename);
/**
* Returns the size of the file.
*
* @param filename The file name.
*
* @return The file size in bytes or -1 on error.
*/
PJ_DECL(pj_off_t) pj_file_size(const char *filename);
/**
* Delete a file.
*
* @param filename The filename.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_file_delete(const char *filename);
/**
* Move a \c oldname to \c newname. If \c newname already exists,
* it will be overwritten.
*
* @param oldname The file to rename.
* @param newname New filename to assign.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_file_move( const char *oldname,
const char *newname);
/**
* Return information about the specified file. The time information in
* the \c stat structure will be in local time.
*
* @param filename The filename.
* @param stat Pointer to variable to receive file information.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_file_getstat(const char *filename, pj_file_stat *stat);
/** @} */
PJ_END_DECL
#endif /* __PJ_FILE_ACCESS_H__ */

View File

@@ -0,0 +1,183 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_FILE_IO_H__
#define __PJ_FILE_IO_H__
/**
* @file file_io.h
* @brief Simple file I/O abstraction.
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_FILE_IO File I/O
* @ingroup PJ_IO
* @{
*
* This file contains functionalities to perform file I/O. The file
* I/O can be implemented with various back-end, either using native
* file API or ANSI stream.
*
* @section pj_file_size_limit_sec Size Limits
*
* There may be limitation on the size that can be handled by the
* #pj_file_setpos() or #pj_file_getpos() functions. The API itself
* uses 64-bit integer for the file offset/position (where available);
* however some backends (such as ANSI) may only support signed 32-bit
* offset resolution.
*
* Reading and writing operation uses signed 32-bit integer to indicate
* the size.
*
*
*/
/**
* These enumerations are used when opening file. Values PJ_O_RDONLY,
* PJ_O_WRONLY, and PJ_O_RDWR are mutually exclusive. Value PJ_O_APPEND
* can only be used when the file is opened for writing.
*/
enum pj_file_access
{
PJ_O_RDONLY = 0x1101, /**< Open file for reading. */
PJ_O_WRONLY = 0x1102, /**< Open file for writing. */
PJ_O_RDWR = 0x1103, /**< Open file for reading and writing.
File will be truncated. */
PJ_O_APPEND = 0x1108, /**< Append to existing file. */
PJ_O_CLOEXEC = 0x1104, /**< Enable unix close-on-exec flag. */
};
/**
* The seek directive when setting the file position with #pj_file_setpos.
*/
enum pj_file_seek_type
{
PJ_SEEK_SET = 0x1201, /**< Offset from beginning of the file. */
PJ_SEEK_CUR = 0x1202, /**< Offset from current position. */
PJ_SEEK_END = 0x1203 /**< Size of the file plus offset. */
};
/**
* Open the file as specified in \c pathname with the specified
* mode, and return the handle in \c fd. All files will be opened
* as binary.
*
* @param pool Pool to allocate memory for the new file descriptor.
* @param pathname The file name to open.
* @param flags Open flags, which is bitmask combination of
* #pj_file_access enum. The flag must be either
* PJ_O_RDONLY, PJ_O_WRONLY, or PJ_O_RDWR. When file
* writing is specified, existing file will be
* truncated unless PJ_O_APPEND is specified.
* @param fd The returned descriptor.
*
* @return PJ_SUCCESS or the appropriate error code on error.
*/
PJ_DECL(pj_status_t) pj_file_open(pj_pool_t *pool,
const char *pathname,
unsigned flags,
pj_oshandle_t *fd);
/**
* Close an opened file descriptor.
*
* @param fd The file descriptor.
*
* @return PJ_SUCCESS or the appropriate error code on error.
*/
PJ_DECL(pj_status_t) pj_file_close(pj_oshandle_t fd);
/**
* Write data with the specified size to an opened file.
*
* @param fd The file descriptor.
* @param data Data to be written to the file.
* @param size On input, specifies the size of data to be written.
* On return, it contains the number of data actually
* written to the file.
*
* @return PJ_SUCCESS or the appropriate error code on error.
*/
PJ_DECL(pj_status_t) pj_file_write(pj_oshandle_t fd,
const void *data,
pj_ssize_t *size);
/**
* Read data from the specified file. When end-of-file condition is set,
* this function will return PJ_SUCCESS but the size will contain zero.
*
* @param fd The file descriptor.
* @param data Pointer to buffer to receive the data.
* @param size On input, specifies the maximum number of data to
* read from the file. On output, it contains the size
* of data actually read from the file. It will contain
* zero when EOF occurs.
*
* @return PJ_SUCCESS or the appropriate error code on error.
* When EOF occurs, the return is PJ_SUCCESS but size
* will report zero.
*/
PJ_DECL(pj_status_t) pj_file_read(pj_oshandle_t fd,
void *data,
pj_ssize_t *size);
/**
* Set file position to new offset according to directive \c whence.
*
* @param fd The file descriptor.
* @param offset The new file position to set.
* @param whence The directive.
*
* @return PJ_SUCCESS or the appropriate error code on error.
*/
PJ_DECL(pj_status_t) pj_file_setpos(pj_oshandle_t fd,
pj_off_t offset,
enum pj_file_seek_type whence);
/**
* Get current file position.
*
* @param fd The file descriptor.
* @param pos On return contains the file position as measured
* from the beginning of the file.
*
* @return PJ_SUCCESS or the appropriate error code on error.
*/
PJ_DECL(pj_status_t) pj_file_getpos(pj_oshandle_t fd,
pj_off_t *pos);
/**
* Flush file buffers.
*
* @param fd The file descriptor.
*
* @return PJ_SUCCESS or the appropriate error code on error.
*/
PJ_DECL(pj_status_t) pj_file_flush(pj_oshandle_t fd);
/** @} */
PJ_END_DECL
#endif /* __PJ_FILE_IO_H__ */

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_GUID_H__
#define __PJ_GUID_H__
/**
* @file guid.h
* @brief GUID Globally Unique Identifier.
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_DS Data Structure.
*/
/**
* @defgroup PJ_GUID Globally Unique Identifier
* @ingroup PJ_DS
* @{
*
* This module provides API to create string that is globally unique.
* If application doesn't require that strong requirement, it can just
* use #pj_create_random_string() instead.
*/
/**
* PJ_GUID_STRING_LENGTH specifies length of GUID string. The value is
* dependent on the algorithm used internally to generate the GUID string.
* If real GUID generator is used, then the length will be between 32 and
* 36 bytes. Application should not assume which algorithm will
* be used by GUID generator.
*
* Regardless of the actual length of the GUID, it will not exceed
* PJ_GUID_MAX_LENGTH characters.
*
* @see pj_GUID_STRING_LENGTH()
* @see PJ_GUID_MAX_LENGTH
*/
PJ_DECL_DATA(const unsigned) PJ_GUID_STRING_LENGTH;
/**
* Get #PJ_GUID_STRING_LENGTH constant.
*/
PJ_DECL(unsigned) pj_GUID_STRING_LENGTH(void);
/**
* PJ_GUID_MAX_LENGTH specifies the maximum length of GUID string,
* regardless of which algorithm to use.
*/
#define PJ_GUID_MAX_LENGTH 36
/**
* Create a globally unique string, which length is PJ_GUID_STRING_LENGTH
* characters. Caller is responsible for preallocating the storage used
* in the string.
*
* @param str The string to store the result.
*
* @return The string.
*/
PJ_DECL(pj_str_t*) pj_generate_unique_string(pj_str_t *str);
/**
* Create a globally unique string in lowercase, which length is
* PJ_GUID_STRING_LENGTH characters. Caller is responsible for preallocating
* the storage used in the string.
*
* @param str The string to store the result.
*
* @return The string.
*/
PJ_DECL(pj_str_t*) pj_generate_unique_string_lower(pj_str_t *str);
/**
* Generate a unique string.
*
* @param pool Pool to allocate memory from.
* @param str The string.
*/
PJ_DECL(void) pj_create_unique_string(pj_pool_t *pool, pj_str_t *str);
/**
* Generate a unique string in lowercase.
*
* @param pool Pool to allocate memory from.
* @param str The string.
*/
PJ_DECL(void) pj_create_unique_string_lower(pj_pool_t *pool, pj_str_t *str);
/**
* @}
*/
PJ_END_DECL
#endif/* __PJ_GUID_H__ */

View File

@@ -0,0 +1,253 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_HASH_H__
#define __PJ_HASH_H__
/**
* @file hash.h
* @brief Hash Table.
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_HASH Hash Table
* @ingroup PJ_DS
* @{
* A hash table is a dictionary in which keys are mapped to array positions by
* hash functions. Having the keys of more than one item map to the same
* position is called a collision. In this library, we will chain the nodes
* that have the same key in a list.
*/
/**
* If this constant is used as keylen, then the key is interpreted as
* NULL terminated string.
*/
#define PJ_HASH_KEY_STRING ((unsigned)-1)
/**
* This indicates the size of of each hash entry.
*/
#define PJ_HASH_ENTRY_BUF_SIZE (3*sizeof(void*) + 2*sizeof(pj_uint32_t))
/**
* Type declaration for entry buffer, used by #pj_hash_set_np()
*/
typedef void *pj_hash_entry_buf[(PJ_HASH_ENTRY_BUF_SIZE+sizeof(void*)-1)/(sizeof(void*))];
/**
* This is the function that is used by the hash table to calculate hash value
* of the specified key.
*
* @param hval the initial hash value, or zero.
* @param key the key to calculate.
* @param keylen the length of the key, or PJ_HASH_KEY_STRING to treat
* the key as null terminated string.
*
* @return the hash value.
*/
PJ_DECL(pj_uint32_t) pj_hash_calc(pj_uint32_t hval,
const void *key, unsigned keylen);
/**
* Convert the key to lowercase and calculate the hash value. The resulting
* string is stored in \c result.
*
* @param hval The initial hash value, normally zero.
* @param result Optional. Buffer to store the result, which must be enough
* to hold the string.
* @param key The input key to be converted and calculated.
*
* @return The hash value.
*/
PJ_DECL(pj_uint32_t) pj_hash_calc_tolower(pj_uint32_t hval,
char *result,
const pj_str_t *key);
/**
* Create a hash table with the specified 'bucket' size.
*
* @param pool the pool from which the hash table will be allocated from.
* @param size the bucket size, which will be round-up to the nearest 2^n-1
*
* @return the hash table.
*/
PJ_DECL(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size);
/**
* Get the value associated with the specified key.
*
* @param ht the hash table.
* @param key the key to look for.
* @param keylen the length of the key, or PJ_HASH_KEY_STRING to use the
* string length of the key.
* @param hval if this argument is not NULL and the value is not zero,
* the value will be used as the computed hash value. If
* the argument is not NULL and the value is zero, it will
* be filled with the computed hash upon return.
*
* @return the value associated with the key, or NULL if the key is not found.
*/
PJ_DECL(void *) pj_hash_get( pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t *hval );
/**
* Variant of #pj_hash_get() with the key being converted to lowercase when
* calculating the hash value.
*
* @see pj_hash_get()
*/
PJ_DECL(void *) pj_hash_get_lower( pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t *hval );
/**
* Associate/disassociate a value with the specified key. If value is not
* NULL and entry already exists, the entry's value will be overwritten.
* If value is not NULL and entry does not exist, a new one will be created
* with the specified pool. Otherwise if value is NULL, entry will be
* deleted if it exists.
*
* @param pool the pool to allocate the new entry if a new entry has to be
* created.
* @param ht the hash table.
* @param key the key. If pool is not specified, the key MUST point to
* buffer that remains valid for the duration of the entry.
* @param keylen the length of the key, or PJ_HASH_KEY_STRING to use the
* string length of the key.
* @param hval if the value is not zero, then the hash table will use
* this value to search the entry's index, otherwise it will
* compute the key. This value can be obtained when calling
* #pj_hash_get().
* @param value value to be associated, or NULL to delete the entry with
* the specified key.
*/
PJ_DECL(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht,
const void *key, unsigned keylen, pj_uint32_t hval,
void *value );
/**
* Variant of #pj_hash_set() with the key being converted to lowercase when
* calculating the hash value.
*
* @see pj_hash_set()
*/
PJ_DECL(void) pj_hash_set_lower( pj_pool_t *pool, pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t hval, void *value );
/**
* Associate/disassociate a value with the specified key. This function works
* like #pj_hash_set(), except that it doesn't use pool (hence the np -- no
* pool suffix). If new entry needs to be allocated, it will use the entry_buf.
*
* @param ht the hash table.
* @param key the key.
* @param keylen the length of the key, or PJ_HASH_KEY_STRING to use the
* string length of the key.
* @param hval if the value is not zero, then the hash table will use
* this value to search the entry's index, otherwise it will
* compute the key. This value can be obtained when calling
* #pj_hash_get().
* @param entry_buf Buffer which will be used for the new entry, when one needs
* to be created.
* @param value value to be associated, or NULL to delete the entry with
* the specified key.
*/
PJ_DECL(void) pj_hash_set_np(pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t hval, pj_hash_entry_buf entry_buf,
void *value);
/**
* Variant of #pj_hash_set_np() with the key being converted to lowercase
* when calculating the hash value.
*
* @see pj_hash_set_np()
*/
PJ_DECL(void) pj_hash_set_np_lower(pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t hval,
pj_hash_entry_buf entry_buf,
void *value);
/**
* Get the total number of entries in the hash table.
*
* @param ht the hash table.
*
* @return the number of entries in the hash table.
*/
PJ_DECL(unsigned) pj_hash_count( pj_hash_table_t *ht );
/**
* Get the iterator to the first element in the hash table.
*
* @param ht the hash table.
* @param it the iterator for iterating hash elements.
*
* @return the iterator to the hash element, or NULL if no element presents.
*/
PJ_DECL(pj_hash_iterator_t*) pj_hash_first( pj_hash_table_t *ht,
pj_hash_iterator_t *it );
/**
* Get the next element from the iterator.
*
* @param ht the hash table.
* @param it the hash iterator.
*
* @return the next iterator, or NULL if there's no more element.
*/
PJ_DECL(pj_hash_iterator_t*) pj_hash_next( pj_hash_table_t *ht,
pj_hash_iterator_t *it );
/**
* Get the value associated with a hash iterator.
*
* @param ht the hash table.
* @param it the hash iterator.
*
* @return the value associated with the current element in iterator.
*/
PJ_DECL(void*) pj_hash_this( pj_hash_table_t *ht,
pj_hash_iterator_t *it );
/**
* @}
*/
PJ_END_DECL
#endif

View File

@@ -0,0 +1,955 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_IOQUEUE_H__
#define __PJ_IOQUEUE_H__
/**
* @file ioqueue.h
* @brief I/O Dispatching Mechanism
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_IO Input/Output
* @brief Input/Output
* @ingroup PJ_OS
*
* This section contains API building blocks to perform network I/O and
* communications. If provides:
* - @ref PJ_SOCK
*\n
* A highly portable socket abstraction, runs on all kind of
* network APIs such as standard BSD socket, Windows socket, Linux
* \b kernel socket, PalmOS networking API, etc.
*
* - @ref pj_addr_resolve
*\n
* Portable address resolution, which implements #pj_gethostbyname().
*
* - @ref PJ_SOCK_SELECT
*\n
* A portable \a select() like API (#pj_sock_select()) which can be
* implemented with various back-ends.
*
* - @ref PJ_IOQUEUE
*\n
* Framework for dispatching network events.
*
* For more information see the modules below.
*/
/**
* @defgroup PJ_IOQUEUE IOQueue: I/O Event Dispatching with Proactor Pattern
* @ingroup PJ_IO
* @{
*
* I/O Queue provides API for performing asynchronous I/O operations. It
* conforms to proactor pattern, which allows application to submit an
* asynchronous operation and to be notified later when the operation has
* completed.
*
* The I/O Queue can work on both socket and file descriptors. For
* asynchronous file operations however, one must make sure that the correct
* file I/O back-end is used, because not all file I/O back-end can be
* used with the ioqueue. Please see \ref PJ_FILE_IO for more details.
*
* The framework works natively in platforms where asynchronous operation API
* exists, such as in Windows NT with IoCompletionPort/IOCP. In other
* platforms, the I/O queue abstracts the operating system's event poll API
* to provide semantics similar to IoCompletionPort with minimal penalties
* (i.e. per ioqueue and per handle mutex protection).
*
* The I/O queue provides more than just unified abstraction. It also:
* - makes sure that the operation uses the most effective way to utilize
* the underlying mechanism, to achieve the maximum theoritical
* throughput possible on a given platform.
* - choose the most efficient mechanism for event polling on a given
* platform.
*
* Currently, the I/O Queue is implemented using:
* - <tt><b>select()</b></tt>, as the common denominator, but the least
* efficient. Also the number of descriptor is limited to
* \c PJ_IOQUEUE_MAX_HANDLES (which by default is 64).
* - <tt><b>/dev/epoll</b></tt> on Linux (user mode and kernel mode),
* a much faster replacement for select() on Linux (and more importantly
* doesn't have limitation on number of descriptors).
* - <b>I/O Completion ports</b> on Windows NT/2000/XP, which is the most
* efficient way to dispatch events in Windows NT based OSes, and most
* importantly, it doesn't have the limit on how many handles to monitor.
* And it works with files (not only sockets) as well.
*
*
* \section pj_ioqueue_concurrency_sec Concurrency Rules
*
* The ioqueue has been fine tuned to allow multiple threads to poll the
* handles simultaneously, to maximize scalability when the application is
* running on multiprocessor systems. When more than one threads are polling
* the ioqueue and there are more than one handles are signaled, more than
* one threads will execute the callback simultaneously to serve the events.
* These parallel executions are completely safe when the events happen for
* two different handles.
*
* However, with multithreading, care must be taken when multiple events
* happen on the same handle, or when event is happening on a handle (and
* the callback is being executed) and application is performing
* unregistration to the handle at the same time.
*
* The treatments of above scenario differ according to the concurrency
* setting that are applied to the handle.
*
* \subsection pj_ioq_concur_set Concurrency Settings for Handles
*
* Concurrency can be set on per handle (key) basis, by using
* #pj_ioqueue_set_concurrency() function. The default key concurrency value
* for the handle is inherited from the key concurrency setting of the ioqueue,
* and the key concurrency setting for the ioqueue can be changed by using
* #pj_ioqueue_set_default_concurrency(). The default key concurrency setting
* for ioqueue itself is controlled by compile time setting
* PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY.
*
* Note that this key concurrency setting only controls whether multiple
* threads are allowed to operate <b>on the same key</b> at the same time.
* The ioqueue itself always allows multiple threads to enter the ioqeuue at
* the same time, and also simultaneous callback calls to <b>differrent
* keys</b> is always allowed regardless to the key concurrency setting.
*
* \subsection pj_ioq_parallel Parallel Callback Executions for the Same Handle
*
* Note that when key concurrency is enabled (i.e. parallel callback calls on
* the same key is allowed; this is the default setting), the ioqueue will only
* perform simultaneous callback executions on the same key when the key has
* invoked multiple pending operations. This could be done for example by
* calling #pj_ioqueue_recvfrom() more than once on the same key, each with
* the same key but different operation key (pj_ioqueue_op_key_t). With this
* scenario, when multiple packets arrive on the key at the same time, more
* than one threads may execute the callback simultaneously, each with the
* same key but different operation key.
*
* When there is only one pending operation on the key (e.g. there is only one
* #pj_ioqueue_recvfrom() invoked on the key), then events occuring to the
* same key will be queued by the ioqueue, thus no simultaneous callback calls
* will be performed.
*
* \subsection pj_ioq_allow_concur Concurrency is Enabled (Default Value)
*
* The default setting for the ioqueue is to allow multiple threads to
* execute callbacks for the same handle/key. This setting is selected to
* promote good performance and scalability for application.
*
* However this setting has a major drawback with regard to synchronization,
* and application MUST carefully follow the following guidelines to ensure
* that parallel access to the key does not cause problems:
*
* - Always note that callback may be called simultaneously for the same
* key.
* - <b>Care must be taken when unregistering a key</b> from the
* ioqueue. Application must take care that when one thread is issuing
* an unregistration, other thread is not simultaneously invoking the
* callback <b>to the same key</b>.
*\n
* This happens because the ioqueue functions are working with a pointer
* to the key, and there is a possible race condition where the pointer
* has been rendered invalid by other threads before the ioqueue has a
* chance to acquire mutex on it.
*
* \subsection pj_ioq_disallow_concur Concurrency is Disabled
*
* Alternatively, application may disable key concurrency to make
* synchronization easier. As noted above, there are three ways to control
* key concurrency setting:
* - by controlling on per handle/key basis, with #pj_ioqueue_set_concurrency().
* - by changing default key concurrency setting on the ioqueue, with
* #pj_ioqueue_set_default_concurrency().
* - by changing the default concurrency on compile time, by declaring
* PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY macro to zero in your config_site.h
*
* \section pj_ioqeuue_examples_sec Examples
*
* For some examples on how to use the I/O Queue, please see:
*
* - I/O Queue TCP test: \src{pjlib/src/pjlib-test/ioq_tcp.c}
* - I/O Queue UDP test: \src{pjlib/src/pjlib-test/ioq_udp.c}
* - I/O Queue Performance test: \src{pjlib/src/pjlib-test/ioq_perf.c}
*/
/**
* This structure describes operation specific key to be submitted to
* I/O Queue when performing the asynchronous operation. This key will
* be returned to the application when completion callback is called.
*
* Application normally wants to attach it's specific data in the
* \c user_data field so that it can keep track of which operation has
* completed when the callback is called. Alternatively, application can
* also extend this struct to include its data, because the pointer that
* is returned in the completion callback will be exactly the same as
* the pointer supplied when the asynchronous function is called.
*/
typedef struct pj_ioqueue_op_key_t
{
void *internal__[32]; /**< Internal I/O Queue data. */
void *activesock_data; /**< Active socket data. */
void *user_data; /**< Application data. */
} pj_ioqueue_op_key_t;
/**
* This structure describes the callbacks to be called when I/O operation
* completes.
*/
typedef struct pj_ioqueue_callback
{
/**
* This callback is called when #pj_ioqueue_recv or #pj_ioqueue_recvfrom
* completes.
*
* @param key The key.
* @param op_key Operation key.
* @param bytes_read >= 0 to indicate the amount of data read,
* otherwise negative value containing the error
* code. To obtain the pj_status_t error code, use
* (pj_status_t code = -bytes_read).
*/
void (*on_read_complete)(pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_ssize_t bytes_read);
/**
* This callback is called when #pj_ioqueue_send or #pj_ioqueue_sendto
* completes.
*
* @param key The key.
* @param op_key Operation key.
* @param bytes_sent >= 0 to indicate the amount of data written,
* otherwise negative value containing the error
* code. To obtain the pj_status_t error code, use
* (pj_status_t code = -bytes_sent).
*/
void (*on_write_complete)(pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_ssize_t bytes_sent);
/**
* This callback is called when #pj_ioqueue_accept completes.
*
* @param key The key.
* @param op_key Operation key.
* @param sock Newly connected socket.
* @param status Zero if the operation completes successfully.
*/
void (*on_accept_complete)(pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_sock_t sock,
pj_status_t status);
/**
* This callback is called when #pj_ioqueue_connect completes.
*
* @param key The key.
* @param status PJ_SUCCESS if the operation completes successfully.
*/
void (*on_connect_complete)(pj_ioqueue_key_t *key,
pj_status_t status);
} pj_ioqueue_callback;
/**
* Types of pending I/O Queue operation. This enumeration is only used
* internally within the ioqueue.
*/
typedef enum pj_ioqueue_operation_e
{
PJ_IOQUEUE_OP_NONE = 0, /**< No operation. */
PJ_IOQUEUE_OP_READ = 1, /**< read() operation. */
PJ_IOQUEUE_OP_RECV = 2, /**< recv() operation. */
PJ_IOQUEUE_OP_RECV_FROM = 4, /**< recvfrom() operation. */
PJ_IOQUEUE_OP_WRITE = 8, /**< write() operation. */
PJ_IOQUEUE_OP_SEND = 16, /**< send() operation. */
PJ_IOQUEUE_OP_SEND_TO = 32, /**< sendto() operation. */
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
PJ_IOQUEUE_OP_ACCEPT = 64, /**< accept() operation. */
PJ_IOQUEUE_OP_CONNECT = 128 /**< connect() operation. */
#endif /* PJ_HAS_TCP */
} pj_ioqueue_operation_e;
/**
* This macro specifies the maximum number of events that can be
* processed by the ioqueue on a single poll cycle, on implementation
* that supports it. The value is only meaningfull when specified
* during PJLIB build.
*/
#ifndef PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL
# define PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL (16)
#endif
/**
* This macro specifies the maximum event candidates collected by each
* polling thread to be able to reach maximum number of processed events
* (i.e: PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL) in each poll cycle.
* An event candidate will be dispatched to application as event unless
* it is already being dispatched by other polling thread. So in order to
* anticipate such race condition, each poll operation should collects its
* event candidates more than PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL, the
* recommended value is (PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL *
* number of polling threads).
*
* The value is only meaningfull when specified during PJLIB build and
* is only effective on multiple polling threads environment.
*/
#if !defined(PJ_IOQUEUE_MAX_CAND_EVENTS) || \
PJ_IOQUEUE_MAX_CAND_EVENTS < PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL
# undef PJ_IOQUEUE_MAX_CAND_EVENTS
# define PJ_IOQUEUE_MAX_CAND_EVENTS PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL
#endif
/**
* When this flag is specified in ioqueue's recv() or send() operations,
* the ioqueue will always mark the operation as asynchronous.
*/
#define PJ_IOQUEUE_ALWAYS_ASYNC ((pj_uint32_t)1 << (pj_uint32_t)31)
/**
* Epoll flags.
*/
typedef enum pj_ioqueue_epoll_flag
{
/** Use of EPOLLEXCLUSIVE.
*/
PJ_IOQUEUE_EPOLL_EXCLUSIVE = 1,
/** Use of EPOLLONESHOT.
*/
PJ_IOQUEUE_EPOLL_ONESHOT = 2,
/**
* Default flag to specify which epoll type to use, which mean to use
* EPOLLEXCLUSIVE if available, otherwise EPOLLONESHOT, otherwise "bare"
* epoll when neither are available.
*/
PJ_IOQUEUE_EPOLL_AUTO = PJ_IOQUEUE_EPOLL_EXCLUSIVE |
PJ_IOQUEUE_EPOLL_ONESHOT,
} pj_ioqueue_epoll_flag;
/**
* Additional settings that can be given during ioqueue creation. Application
* MUST initialize this structure with #pj_ioqueue_cfg_default().
*/
typedef struct pj_ioqueue_cfg
{
/**
* Specify flags to control e.g. how events are handled when epoll backend
* is used on Linux. The values are combination of pj_ioqueue_epoll_flag.
* The default value is PJ_IOQUEUE_DEFAULT_EPOLL_FLAGS, which by default
* is set to PJ_IOQUEUE_EPOLL_AUTO. This setting will be ignored for other
* ioqueue backends.
*/
unsigned epoll_flags;
/**
* Default concurrency for the handles registered to this ioqueue. Setting
* this to non-zero enables a handle to process more than one operations
* at the same time using different threads. Default is
* PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY. This setting is equivalent to
* calling pj_ioqueue_set_default_concurrency() after creating the ioqueue.
*/
pj_bool_t default_concurrency;
} pj_ioqueue_cfg;
/**
* Initialize the ioqueue configuration with the default values.
*
* @param cfg The configuration to be initialized.
*/
PJ_DECL(void) pj_ioqueue_cfg_default(pj_ioqueue_cfg *cfg);
/**
* Return the name of the ioqueue implementation.
*
* @return Implementation name.
*/
PJ_DECL(const char*) pj_ioqueue_name(void);
/**
* Create a new I/O Queue framework.
*
* @param pool The pool to allocate the I/O queue structure.
* @param max_fd The maximum number of handles to be supported, which
* should not exceed PJ_IOQUEUE_MAX_HANDLES.
* @param ioqueue Pointer to hold the newly created I/O Queue.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pj_ioqueue_create( pj_pool_t *pool,
pj_size_t max_fd,
pj_ioqueue_t **ioqueue);
/**
* Create a new I/O Queue framework.
*
* @param pool The pool to allocate the I/O queue structure.
* @param max_fd The maximum number of handles to be supported, which
* should not exceed PJ_IOQUEUE_MAX_HANDLES.
* @param cfg Optional ioqueue configuration. Application must
* initialize this structure with pj_ioqueue_cfg_default()
* first. If this is not specified, default config values
* as set pj_ioqueue_cfg_default() by will be used.
* @param ioqueue Pointer to hold the newly created I/O Queue.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pj_ioqueue_create2( pj_pool_t *pool,
pj_size_t max_fd,
const pj_ioqueue_cfg *cfg,
pj_ioqueue_t **ioqueue);
/**
* Destroy the I/O queue.
*
* @param ioque The I/O Queue to be destroyed.
*
* @return PJ_SUCCESS if success.
*/
PJ_DECL(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioque );
/**
* Set the lock object to be used by the I/O Queue. This function can only
* be called right after the I/O queue is created, before any handle is
* registered to the I/O queue.
*
* Initially the I/O queue is created with non-recursive mutex protection.
* Applications can supply alternative lock to be used by calling this
* function.
*
* @param ioque The ioqueue instance.
* @param lock The lock to be used by the ioqueue.
* @param auto_delete In non-zero, the lock will be deleted by the ioqueue.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_set_lock( pj_ioqueue_t *ioque,
pj_lock_t *lock,
pj_bool_t auto_delete );
/**
* Set default concurrency policy for this ioqueue. If this function is not
* called, the default concurrency policy for the ioqueue is controlled by
* compile time setting PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY.
*
* Note that changing the concurrency setting to the ioqueue will only affect
* subsequent key registrations. To modify the concurrency setting for
* individual key, use #pj_ioqueue_set_concurrency().
*
* @param ioqueue The ioqueue instance.
* @param allow Non-zero to allow concurrent callback calls, or
* PJ_FALSE to disallow it.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_set_default_concurrency(pj_ioqueue_t *ioqueue,
pj_bool_t allow);
/**
* Register a socket to the I/O queue framework.
* When a socket is registered to the IOQueue, it may be modified to use
* non-blocking IO. If it is modified, there is no guarantee that this
* modification will be restored after the socket is unregistered.
*
* @param pool To allocate the resource for the specified handle,
* which must be valid until the handle/key is unregistered
* from I/O Queue.
* @param ioque The I/O Queue.
* @param sock The socket.
* @param user_data User data to be associated with the key, which can be
* retrieved later.
* @param cb Callback to be called when I/O operation completes.
* @param key Pointer to receive the key to be associated with this
* socket. Subsequent I/O queue operation will need this
* key.
*
* @return PJ_SUCCESS on success, or the error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool,
pj_ioqueue_t *ioque,
pj_sock_t sock,
void *user_data,
const pj_ioqueue_callback *cb,
pj_ioqueue_key_t **key );
/**
* Variant of pj_ioqueue_register_sock() with additional group lock parameter.
* If group lock is set for the key, the key will add the reference counter
* when the socket is registered and decrease it when it is destroyed.
*/
PJ_DECL(pj_status_t) pj_ioqueue_register_sock2(pj_pool_t *pool,
pj_ioqueue_t *ioque,
pj_sock_t sock,
pj_grp_lock_t *grp_lock,
void *user_data,
const pj_ioqueue_callback *cb,
pj_ioqueue_key_t **key );
/**
* Unregister from the I/O Queue framework. Caller must make sure that
* the key doesn't have any pending operations before calling this function,
* by calling #pj_ioqueue_is_pending() for all previously submitted
* operations except asynchronous connect, and if necessary call
* #pj_ioqueue_post_completion() to cancel the pending operations.
*
* Note that asynchronous connect operation will automatically be
* cancelled during the unregistration.
*
* Also note that when I/O Completion Port backend is used, application
* MUST close the handle immediately after unregistering the key. This is
* because there is no unregistering API for IOCP. The only way to
* unregister the handle from IOCP is to close the handle.
*
* @param key The key that was previously obtained from registration.
*
* @return PJ_SUCCESS on success or the error code.
*
* @see pj_ioqueue_is_pending
*/
PJ_DECL(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key );
/**
* Get user data associated with an ioqueue key.
*
* @param key The key that was previously obtained from registration.
*
* @return The user data associated with the descriptor, or NULL
* on error or if no data is associated with the key during
* registration.
*/
PJ_DECL(void*) pj_ioqueue_get_user_data( pj_ioqueue_key_t *key );
/**
* Set or change the user data to be associated with the file descriptor or
* handle or socket descriptor.
*
* @param key The key that was previously obtained from registration.
* @param user_data User data to be associated with the descriptor.
* @param old_data Optional parameter to retrieve the old user data.
*
* @return PJ_SUCCESS on success or the error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_set_user_data( pj_ioqueue_key_t *key,
void *user_data,
void **old_data);
/**
* Configure whether the ioqueue is allowed to call the key's callback
* concurrently/in parallel. The default concurrency setting for the key
* is controlled by ioqueue's default concurrency value, which can be
* changed by calling #pj_ioqueue_set_default_concurrency().
*
* If concurrency is allowed for the key, it means that if there are more
* than one pending operations complete simultaneously, more than one
* threads may call the key's callback at the same time. This generally
* would promote good scalability for application, at the expense of more
* complexity to manage the concurrent accesses in application's code.
*
* Alternatively application may disable the concurrent access by
* setting the \a allow flag to false. With concurrency disabled, only
* one thread can call the key's callback at one time.
*
* @param key The key that was previously obtained from registration.
* @param allow Set this to non-zero to allow concurrent callback calls
* and zero (PJ_FALSE) to disallow it.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_set_concurrency(pj_ioqueue_key_t *key,
pj_bool_t allow);
/**
* Acquire the key's mutex. When the key's concurrency is disabled,
* application may call this function to synchronize its operation
* with the key's callback (i.e. this function will block until the
* key's callback returns).
*
* @param key The key that was previously obtained from registration.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_lock_key(pj_ioqueue_key_t *key);
/**
* Try to acquire the key's mutex. When the key's concurrency is disabled,
* application may call this function to synchronize its operation
* with the key's callback.
*
* @param key The key that was previously obtained from registration.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_trylock_key(pj_ioqueue_key_t *key);
/**
* Release the lock previously acquired with pj_ioqueue_lock_key().
*
* @param key The key that was previously obtained from registration.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_unlock_key(pj_ioqueue_key_t *key);
/**
* Initialize operation key.
*
* @param op_key The operation key to be initialied.
* @param size The size of the operation key.
*/
PJ_DECL(void) pj_ioqueue_op_key_init( pj_ioqueue_op_key_t *op_key,
pj_size_t size );
/**
* Check if operation is pending on the specified operation key.
* The \c op_key must have been initialized with #pj_ioqueue_op_key_init()
* or submitted as pending operation before, or otherwise the result
* is undefined.
*
* @param key The key.
* @param op_key The operation key, previously submitted to any of
* the I/O functions and has returned PJ_EPENDING.
*
* @return Non-zero if operation is still pending.
*/
PJ_DECL(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key );
/**
* Post completion status to the specified operation key and call the
* appropriate callback. When the callback is called, the number of bytes
* received in read/write callback or the status in accept/connect callback
* will be set from the \c bytes_status parameter.
*
* @param key The key.
* @param op_key Pending operation key.
* @param bytes_status Number of bytes or status to be set. A good value
* to put here is -PJ_ECANCELLED.
*
* @return PJ_SUCCESS if completion status has been successfully
* sent.
*/
PJ_DECL(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_ssize_t bytes_status );
/**
* Clear ioqueue key states. This function will cancel any outstanding
* operations on that key, without invoking any completion callback.
* After calling this function, application should reinit its all operation
* keys, i.e: using pj_ioqueue_op_key_init(), before reusing them.
*
* @param key The key.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_clear_key( pj_ioqueue_key_t *key );
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
/**
* Instruct I/O Queue to accept incoming connection on the specified
* listening socket. This function will return immediately (i.e. non-blocking)
* regardless whether a connection is immediately available. If the function
* can't complete immediately, the caller will be notified about the incoming
* connection when it calls pj_ioqueue_poll(). If a new connection is
* immediately available, the function returns PJ_SUCCESS with the new
* connection; in this case, the callback WILL NOT be called.
*
* @param key The key which registered to the server socket.
* @param op_key An operation specific key to be associated with the
* pending operation, so that application can keep track of
* which operation has been completed when the callback is
* called.
* @param new_sock Argument which contain pointer to receive the new socket
* for the incoming connection.
* @param local Optional argument which contain pointer to variable to
* receive local address.
* @param remote Optional argument which contain pointer to variable to
* receive the remote address.
* @param addrlen On input, contains the length of the buffer for the
* address, and on output, contains the actual length of the
* address. This argument is optional.
* @return
* - PJ_SUCCESS When connection is available immediately, and the
* parameters will be updated to contain information about
* the new connection. In this case, a completion callback
* WILL NOT be called.
* - PJ_EPENDING If no connection is available immediately. When a new
* connection arrives, the callback will be called.
* - non-zero which indicates the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_accept( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_sock_t *new_sock,
pj_sockaddr_t *local,
pj_sockaddr_t *remote,
int *addrlen );
/**
* Initiate non-blocking socket connect. If the socket can NOT be connected
* immediately, asynchronous connect() will be scheduled and caller will be
* notified via completion callback when it calls pj_ioqueue_poll(). If
* socket is connected immediately, the function returns PJ_SUCCESS and
* completion callback WILL NOT be called.
*
* @param key The key associated with TCP socket
* @param addr The remote address.
* @param addrlen The remote address length.
*
* @return
* - PJ_SUCCESS If socket is connected immediately. In this case, the
* completion callback WILL NOT be called.
* - PJ_EPENDING If operation is queued, or
* - non-zero Indicates the error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key,
const pj_sockaddr_t *addr,
int addrlen );
#endif /* PJ_HAS_TCP */
/**
* Poll the I/O Queue for completed events.
*
* Note: polling the ioqueue is not necessary in Symbian. Please see
* @ref PJ_SYMBIAN_OS for more info.
*
* @param ioque the I/O Queue.
* @param timeout polling timeout, or NULL if the thread wishes to wait
* indefinetely for the event.
*
* @return
* - zero if timed out (no event).
* - (<0) if error occured during polling. Callback will NOT be called.
* - (>1) to indicate numbers of events. Callbacks have been called.
*/
PJ_DECL(int) pj_ioqueue_poll( pj_ioqueue_t *ioque,
const pj_time_val *timeout);
/**
* Instruct the I/O Queue to read from the specified handle. This function
* returns immediately (i.e. non-blocking) regardless whether some data has
* been transferred. If the operation can't complete immediately, caller will
* be notified about the completion when it calls pj_ioqueue_poll(). If data
* is immediately available, the function will return PJ_SUCCESS and the
* callback WILL NOT be called.
*
* @param key The key that uniquely identifies the handle.
* @param op_key An operation specific key to be associated with the
* pending operation, so that application can keep track of
* which operation has been completed when the callback is
* called. Caller must make sure that this key remains
* valid until the function completes.
* @param buffer The buffer to hold the read data. The caller MUST make sure
* that this buffer remain valid until the framework completes
* reading the handle.
* @param length On input, it specifies the size of the buffer. If data is
* available to be read immediately, the function returns
* PJ_SUCCESS and this argument will be filled with the
* amount of data read. If the function is pending, caller
* will be notified about the amount of data read in the
* callback. This parameter can point to local variable in
* caller's stack and doesn't have to remain valid for the
* duration of pending operation.
* @param flags Recv flag. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then
* the function will never return PJ_SUCCESS.
*
* @return
* - PJ_SUCCESS If immediate data has been received in the buffer. In this
* case, the callback WILL NOT be called.
* - PJ_EPENDING If the operation has been queued, and the callback will be
* called when data has been received.
* - non-zero The return value indicates the error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
void *buffer,
pj_ssize_t *length,
pj_uint32_t flags );
/**
* This function behaves similarly as #pj_ioqueue_recv(), except that it is
* normally called for socket, and the remote address will also be returned
* along with the data. Caller MUST make sure that both buffer and addr
* remain valid until the framework completes reading the data.
*
* @param key The key that uniquely identifies the handle.
* @param op_key An operation specific key to be associated with the
* pending operation, so that application can keep track of
* which operation has been completed when the callback is
* called.
* @param buffer The buffer to hold the read data. The caller MUST make sure
* that this buffer remain valid until the framework completes
* reading the handle.
* @param length On input, it specifies the size of the buffer. If data is
* available to be read immediately, the function returns
* PJ_SUCCESS and this argument will be filled with the
* amount of data read. If the function is pending, caller
* will be notified about the amount of data read in the
* callback. This parameter can point to local variable in
* caller's stack and doesn't have to remain valid for the
* duration of pending operation.
* @param flags Recv flag. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then
* the function will never return PJ_SUCCESS.
* @param addr Optional Pointer to buffer to receive the address.
* @param addrlen On input, specifies the length of the address buffer.
* On output, it will be filled with the actual length of
* the address. This argument can be NULL if \c addr is not
* specified.
*
* @return
* - PJ_SUCCESS If immediate data has been received. In this case, the
* callback must have been called before this function
* returns, and no pending operation is scheduled.
* - PJ_EPENDING If the operation has been queued.
* - non-zero The return value indicates the error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
void *buffer,
pj_ssize_t *length,
pj_uint32_t flags,
pj_sockaddr_t *addr,
int *addrlen);
/**
* Instruct the I/O Queue to write to the handle. This function will return
* immediately (i.e. non-blocking) regardless whether some data has been
* transferred. If the function can't complete immediately, the caller will
* be notified about the completion when it calls pj_ioqueue_poll(). If
* operation completes immediately and data has been transferred, the function
* returns PJ_SUCCESS and the callback will NOT be called.
*
* @param key The key that identifies the handle.
* @param op_key An operation specific key to be associated with the
* pending operation, so that application can keep track of
* which operation has been completed when the callback is
* called.
* @param data The data to send. Caller MUST make sure that this buffer
* remains valid until the write operation completes.
* @param length On input, it specifies the length of data to send. When
* data was sent immediately, this function returns PJ_SUCCESS
* and this parameter contains the length of data sent. If
* data can not be sent immediately, an asynchronous operation
* is scheduled and caller will be notified via callback the
* number of bytes sent. This parameter can point to local
* variable on caller's stack and doesn't have to remain
* valid until the operation has completed.
* @param flags Send flags. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then
* the function will never return PJ_SUCCESS.
*
* @return
* - PJ_SUCCESS If data was immediately transferred. In this case, no
* pending operation has been scheduled and the callback
* WILL NOT be called.
* - PJ_EPENDING If the operation has been queued. Once data base been
* transferred, the callback will be called.
* - non-zero The return value indicates the error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
const void *data,
pj_ssize_t *length,
pj_uint32_t flags );
/**
* Instruct the I/O Queue to write to the handle. This function will return
* immediately (i.e. non-blocking) regardless whether some data has been
* transferred. If the function can't complete immediately, the caller will
* be notified about the completion when it calls pj_ioqueue_poll(). If
* operation completes immediately and data has been transferred, the function
* returns PJ_SUCCESS and the callback will NOT be called.
*
* @param key the key that identifies the handle.
* @param op_key An operation specific key to be associated with the
* pending operation, so that application can keep track of
* which operation has been completed when the callback is
* called.
* @param data the data to send. Caller MUST make sure that this buffer
* remains valid until the write operation completes.
* @param length On input, it specifies the length of data to send. When
* data was sent immediately, this function returns PJ_SUCCESS
* and this parameter contains the length of data sent. If
* data can not be sent immediately, an asynchronous operation
* is scheduled and caller will be notified via callback the
* number of bytes sent. This parameter can point to local
* variable on caller's stack and doesn't have to remain
* valid until the operation has completed.
* @param flags send flags. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then
* the function will never return PJ_SUCCESS.
* @param addr Optional remote address.
* @param addrlen Remote address length, \c addr is specified.
*
* @return
* - PJ_SUCCESS If data was immediately written.
* - PJ_EPENDING If the operation has been queued.
* - non-zero The return value indicates the error code.
*/
PJ_DECL(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
const void *data,
pj_ssize_t *length,
pj_uint32_t flags,
const pj_sockaddr_t *addr,
int addrlen);
/**
* Get the underlying OS handle associated with an ioqueue instance.
*
* @param ioqueue The ioqueue instance.
*
* @return The OS handle associated with the instance.
* For epoll/kqueue this will be a pointer to the file
* descriptor. For all other platforms, this will be a pointer
* to a platform-specific handle.
* If no handle is available, NULL will be returned.
*/
PJ_DECL(pj_oshandle_t) pj_ioqueue_get_os_handle( pj_ioqueue_t *ioqueue );
/**
* @}
*/
PJ_END_DECL
#endif /* __PJ_IOQUEUE_H__ */

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_IP_ROUTE_H__
#define __PJ_IP_ROUTE_H__
/**
* @file ip_helper.h
* @brief IP helper API
*/
#include <pj/sock.h>
#include <pj/string.h>
PJ_BEGIN_DECL
/**
* @defgroup pj_ip_helper IP Interface and Routing Helper
* @ingroup PJ_IO
* @{
*
* This module provides functions to query local host's IP interface and
* routing table.
*/
/**
* This structure describes IP routing entry.
*/
typedef union pj_ip_route_entry
{
/** IP routing entry for IP version 4 routing */
struct
{
pj_in_addr if_addr; /**< Local interface IP address. */
pj_in_addr dst_addr; /**< Destination IP address. */
pj_in_addr mask; /**< Destination mask. */
} ipv4;
} pj_ip_route_entry;
/**
* This structure describes options for pj_enum_ip_interface2().
*/
typedef struct pj_enum_ip_option
{
/**
* Family of the address to be retrieved. Application may specify
* pj_AF_UNSPEC() to retrieve all addresses, or pj_AF_INET() or
* pj_AF_INET6() to retrieve interfaces with specific address family.
*
* Default: pj_AF_UNSPEC().
*/
int af;
/**
* IPv6 addresses can have a DEPRECATED flag, if this flag is set, any
* DEPRECATED IPv6 address will be omitted. Currently this is only
* available for Linux, on other platforms, if this flag is set,
* pj_enum_ip_interface2() will return PJ_ENOTSUP.
*
* Default: PJ_FALSE.
*/
pj_bool_t omit_deprecated_ipv6;
} pj_enum_ip_option;
/**
* Get default values of IP enumeration option.
*
* @param opt The IP enumeration option.
*/
PJ_INLINE(void) pj_enum_ip_option_default(pj_enum_ip_option *opt)
{
pj_bzero(opt, sizeof(*opt));
}
/**
* Enumerate the local IP interfaces currently active in the host.
*
* @param af Family of the address to be retrieved. Application
* may specify pj_AF_UNSPEC() to retrieve all addresses,
* or pj_AF_INET() or pj_AF_INET6() to retrieve interfaces
* with specific address family.
* @param count On input, specify the number of entries. On output,
* it will be filled with the actual number of entries.
* @param ifs Array of socket addresses, which address part will
* be filled with the interface address. The address
* family part will be initialized with the address
* family of the IP address.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_enum_ip_interface(int af,
unsigned *count,
pj_sockaddr ifs[]);
/**
* Enumerate the local IP interfaces currently active in the host with
* capability to filter DEPRECATED IPv6 addresses (currently only for Linux).
*
* @param opt The option, default option will be used if NULL.
* @param count On input, specify the number of entries. On output,
* it will be filled with the actual number of entries.
* @param ifs Array of socket (with flags) addresses, which address part
* will be filled with the interface address. The address
* family part will be initialized with the address
* family of the IP address.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_enum_ip_interface2(const pj_enum_ip_option *opt,
unsigned *count,
pj_sockaddr ifs[]);
/**
* Enumerate the IP routing table for this host.
*
* @param count On input, specify the number of routes entries. On output,
* it will be filled with the actual number of route entries.
* @param routes Array of IP routing entries.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_enum_ip_route(unsigned *count,
pj_ip_route_entry routes[]);
/** @} */
PJ_END_DECL
#endif /* __PJ_IP_ROUTE_H__ */

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2017 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2017 George Joseph <gjoseph@digium.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_LIMITS_H__
#define __PJ_LIMITS_H__
/**
* @file limits.h
* @brief Common min and max values
*/
#include <pj/compat/limits.h>
/** Maximum value for signed 32-bit integer. */
#define PJ_MAXINT32 0x7fffffff
/** Minimum value for signed 32-bit integer. */
#define PJ_MININT32 0x80000000
/** Maximum value for unsigned 16-bit integer. */
#define PJ_MAXUINT16 0xffff
/** Maximum value for unsigned char. */
#define PJ_MAXUINT8 0xff
/** Maximum value for long. */
#define PJ_MAXLONG LONG_MAX
/** Minimum value for long. */
#define PJ_MINLONG LONG_MIN
/** Minimum value for unsigned long. */
#define PJ_MAXULONG ULONG_MAX
/** Maximum value for generic unsigned integer. */
#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
# define PJ_MAXUINT 0xffffffffffffffffULL
#else
# define PJ_MAXUINT 0xffffffff
#endif
#endif /* __PJ_LIMITS_H__ */

View File

@@ -0,0 +1,268 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_LIST_H__
#define __PJ_LIST_H__
/**
* @file list.h
* @brief Linked List data structure.
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/*
* @defgroup PJ_DS Data Structure.
*/
/**
* @defgroup PJ_LIST Linked List
* @ingroup PJ_DS
* @{
*
* List in PJLIB is implemented as doubly-linked list, and it won't require
* dynamic memory allocation (just as all PJLIB data structures). The list here
* should be viewed more like a low level C list instead of high level C++ list
* (which normally are easier to use but require dynamic memory allocations),
* therefore all caveats with C list apply here too (such as you can NOT put
* a node in more than one lists).
*
* \section pj_list_example_sec Examples
*
* See below for examples on how to manipulate linked list:
* - List sample: \src{pjlib/src/pjlib-samples/list.c}
* - List test: \src{pjlib/src/pjlib-test/list.c}
*/
/**
* Use this macro in the start of the structure declaration to declare that
* the structure can be used in the linked list operation. This macro simply
* declares additional member @a prev and @a next to the structure.
* @hideinitializer
*/
#define PJ_DECL_LIST_MEMBER(type) \
/** List @a prev. */ \
type *prev; \
/** List @a next. */ \
type *next
/**
* This structure describes generic list node and list. The owner of this list
* must initialize the 'value' member to an appropriate value (typically the
* owner itself).
*/
struct pj_list
{
PJ_DECL_LIST_MEMBER(void);
} PJ_ATTR_MAY_ALIAS; /* may_alias avoids warning with gcc-4.4 -Wall -O2 */
/**
* Initialize the list.
* Initially, the list will have no member, and function pj_list_empty() will
* always return nonzero (which indicates TRUE) for the newly initialized
* list.
*
* @param node The list head.
*/
PJ_INLINE(void) pj_list_init(pj_list_type * node)
{
((pj_list*)node)->next = ((pj_list*)node)->prev = node;
}
/**
* Check that the list is empty.
*
* @param node The list head.
*
* @return Non-zero if the list is empty, or zero if it is not empty.
*
*/
PJ_INLINE(int) pj_list_empty(const pj_list_type * node)
{
return ((pj_list*)node)->next == node;
}
/**
* Insert the node to the list before the specified element position.
*
* @param pos The element to which the node will be inserted before.
* @param node The element to be inserted.
*
*/
PJ_IDECL(void) pj_list_insert_before(pj_list_type *pos, pj_list_type *node);
/**
* Insert the node to the back of the list. This is just an alias for
* #pj_list_insert_before().
*
* @param list The list.
* @param node The element to be inserted.
*/
PJ_INLINE(void) pj_list_push_back(pj_list_type *list, pj_list_type *node)
{
pj_list_insert_before(list, node);
}
/**
* Inserts all nodes in \a nodes to the target list.
*
* @param lst The target list.
* @param nodes Nodes list.
*/
PJ_IDECL(void) pj_list_insert_nodes_before(pj_list_type *lst,
pj_list_type *nodes);
/**
* Insert a node to the list after the specified element position.
*
* @param pos The element in the list which will precede the inserted
* element.
* @param node The element to be inserted after the position element.
*
*/
PJ_IDECL(void) pj_list_insert_after(pj_list_type *pos, pj_list_type *node);
/**
* Insert the node to the front of the list. This is just an alias for
* #pj_list_insert_after().
*
* @param list The list.
* @param node The element to be inserted.
*/
PJ_INLINE(void) pj_list_push_front(pj_list_type *list, pj_list_type *node)
{
pj_list_insert_after(list, node);
}
/**
* Insert all nodes in \a nodes to the target list.
*
* @param lst The target list.
* @param nodes Nodes list.
*/
PJ_IDECL(void) pj_list_insert_nodes_after(pj_list_type *lst,
pj_list_type *nodes);
/**
* Remove elements from the source list, and insert them to the destination
* list. The elements of the source list will occupy the
* front elements of the target list. Note that the node pointed by \a list2
* itself is not considered as a node, but rather as the list descriptor, so
* it will not be inserted to the \a list1. The elements to be inserted starts
* at \a list2->next. If \a list2 is to be included in the operation, use
* \a pj_list_insert_nodes_before.
*
* @param list1 The destination list.
* @param list2 The source list.
*
*/
PJ_IDECL(void) pj_list_merge_first(pj_list_type *list1, pj_list_type *list2);
/**
* Remove elements from the second list argument, and insert them to the list
* in the first argument. The elements from the second list will be appended
* to the first list. Note that the node pointed by \a list2
* itself is not considered as a node, but rather as the list descriptor, so
* it will not be inserted to the \a list1. The elements to be inserted starts
* at \a list2->next. If \a list2 is to be included in the operation, use
* \a pj_list_insert_nodes_before.
*
* @param list1 The element in the list which will precede the inserted
* element.
* @param list2 The element in the list to be inserted.
*
*/
PJ_IDECL(void) pj_list_merge_last( pj_list_type *list1, pj_list_type *list2);
/**
* Erase the node from the list it currently belongs.
*
* @param node The element to be erased.
*/
PJ_IDECL(void) pj_list_erase(pj_list_type *node);
/**
* Find node in the list.
*
* @param list The list head.
* @param node The node element to be searched.
*
* @return The node itself if it is found in the list, or NULL if it is not
* found in the list.
*/
PJ_IDECL(pj_list_type*) pj_list_find_node(pj_list_type *list,
pj_list_type *node);
/**
* Search the list for the specified value, using the specified comparison
* function. This function iterates on nodes in the list, started with the
* first node, and call the user supplied comparison function until the
* comparison function returns ZERO.
*
* @param list The list head.
* @param value The user defined value to be passed in the comparison
* function
* @param comp The comparison function, which should return ZERO to
* indicate that the searched value is found.
*
* @return The first node that matched, or NULL if it is not found.
*/
PJ_IDECL(pj_list_type*) pj_list_search(pj_list_type *list, void *value,
int (*comp)(void *value,
const pj_list_type *node)
);
/**
* Traverse the list to get the number of elements in the list.
*
* @param list The list head.
*
* @return Number of elements.
*/
PJ_IDECL(pj_size_t) pj_list_size(const pj_list_type *list);
/**
* @}
*/
#if PJ_FUNCTIONS_ARE_INLINED
# include "list_i.h"
#endif
PJ_END_DECL
#endif /* __PJ_LIST_H__ */

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Internal */
PJ_INLINE(void) pj_link_node(pj_list_type *prev, pj_list_type *next)
{
((pj_list*)prev)->next = next;
((pj_list*)next)->prev = prev;
}
PJ_IDEF(void) pj_list_insert_after(pj_list_type *pos, pj_list_type *node)
{
((pj_list*)node)->prev = pos;
((pj_list*)node)->next = ((pj_list*)pos)->next;
((pj_list*) ((pj_list*)pos)->next) ->prev = node;
((pj_list*)pos)->next = node;
}
PJ_IDEF(void) pj_list_insert_before(pj_list_type *pos, pj_list_type *node)
{
pj_list_insert_after(((pj_list*)pos)->prev, node);
}
PJ_IDEF(void) pj_list_insert_nodes_after(pj_list_type *pos, pj_list_type *lst)
{
pj_list *lst_last = (pj_list *) ((pj_list*)lst)->prev;
pj_list *pos_next = (pj_list *) ((pj_list*)pos)->next;
pj_link_node(pos, lst);
pj_link_node(lst_last, pos_next);
}
PJ_IDEF(void) pj_list_insert_nodes_before(pj_list_type *pos, pj_list_type *lst)
{
pj_list_insert_nodes_after(((pj_list*)pos)->prev, lst);
}
PJ_IDEF(void) pj_list_merge_last(pj_list_type *lst1, pj_list_type *lst2)
{
if (!pj_list_empty(lst2)) {
pj_link_node(((pj_list*)lst1)->prev, ((pj_list*)lst2)->next);
pj_link_node(((pj_list*)lst2)->prev, lst1);
pj_list_init(lst2);
}
}
PJ_IDEF(void) pj_list_merge_first(pj_list_type *lst1, pj_list_type *lst2)
{
if (!pj_list_empty(lst2)) {
pj_link_node(((pj_list*)lst2)->prev, ((pj_list*)lst1)->next);
pj_link_node(((pj_list*)lst1), ((pj_list*)lst2)->next);
pj_list_init(lst2);
}
}
PJ_IDEF(void) pj_list_erase(pj_list_type *node)
{
pj_link_node( ((pj_list*)node)->prev, ((pj_list*)node)->next);
/* It'll be safer to init the next/prev fields to itself, to
* prevent multiple erase() from corrupting the list. See
* ticket #520 for one sample bug.
*/
pj_list_init(node);
}
PJ_IDEF(pj_list_type*) pj_list_find_node(pj_list_type *list, pj_list_type *node)
{
pj_list *p = (pj_list *) ((pj_list*)list)->next;
while (p != list && p != node)
p = (pj_list *) p->next;
return p==node ? p : NULL;
}
PJ_IDEF(pj_list_type*) pj_list_search(pj_list_type *list, void *value,
int (*comp)(void *value, const pj_list_type *node))
{
pj_list *p = (pj_list *) ((pj_list*)list)->next;
while (p != list && (*comp)(value, p) != 0)
p = (pj_list *) p->next;
return p==list ? NULL : p;
}
PJ_IDEF(pj_size_t) pj_list_size(const pj_list_type *list)
{
const pj_list *node = (const pj_list*) ((const pj_list*)list)->next;
pj_size_t count = 0;
while (node != list) {
++count;
node = (pj_list*)node->next;
}
return count;
}

View File

@@ -0,0 +1,453 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_LOCK_H__
#define __PJ_LOCK_H__
/**
* @file lock.h
* @brief Higher abstraction for locking objects.
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_LOCK Lock Objects
* @ingroup PJ_OS
* @{
*
* <b>Lock Objects</b> are higher abstraction for different lock mechanisms.
* It offers the same API for manipulating different lock types (e.g.
* @ref PJ_MUTEX "mutex", @ref PJ_SEM "semaphores", or null locks).
* Because Lock Objects have the same API for different types of lock
* implementation, it can be passed around in function arguments. As the
* result, it can be used to control locking policy for a particular
* feature.
*/
/**
* Create simple, non recursive mutex lock object.
*
* @param pool Memory pool.
* @param name Lock object's name.
* @param lock Pointer to store the returned handle.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_lock_create_simple_mutex( pj_pool_t *pool,
const char *name,
pj_lock_t **lock );
/**
* Create recursive mutex lock object.
*
* @param pool Memory pool.
* @param name Lock object's name.
* @param lock Pointer to store the returned handle.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_lock_create_recursive_mutex( pj_pool_t *pool,
const char *name,
pj_lock_t **lock );
/**
* Create NULL mutex. A NULL mutex doesn't actually have any synchronization
* object attached to it.
*
* @param pool Memory pool.
* @param name Lock object's name.
* @param lock Pointer to store the returned handle.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_lock_create_null_mutex( pj_pool_t *pool,
const char *name,
pj_lock_t **lock );
#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
/**
* Create semaphore lock object.
*
* @param pool Memory pool.
* @param name Lock object's name.
* @param initial Initial value of the semaphore.
* @param max Maximum value of the semaphore.
* @param lock Pointer to store the returned handle.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_lock_create_semaphore( pj_pool_t *pool,
const char *name,
unsigned initial,
unsigned max,
pj_lock_t **lock );
#endif /* PJ_HAS_SEMAPHORE */
/**
* Acquire lock on the specified lock object.
*
* @param lock The lock object.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_lock_acquire( pj_lock_t *lock );
/**
* Try to acquire lock on the specified lock object.
*
* @param lock The lock object.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_lock_tryacquire( pj_lock_t *lock );
/**
* Release lock on the specified lock object.
*
* @param lock The lock object.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_lock_release( pj_lock_t *lock );
/**
* Destroy the lock object.
*
* @param lock The lock object.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_lock_destroy( pj_lock_t *lock );
/** @} */
/**
* @defgroup PJ_GRP_LOCK Group Lock
* @ingroup PJ_LOCK
* @{
*
* Group lock is a synchronization object to manage concurrency among members
* within the same logical group. Example of such groups are:
*
* - dialog, which has members such as the dialog itself, an invite session,
* and several transactions
* - ICE, which has members such as ICE stream transport, ICE session, STUN
* socket, TURN socket, and down to ioqueue key
*
* Group lock has three functions:
*
* - mutual exclusion: to protect resources from being accessed by more than
* one threads at the same time
* - session management: to make sure that the resource is not destroyed
* while others are still using or about to use it.
* - lock coordinator: to provide uniform lock ordering among more than one
* lock objects, which is necessary to avoid deadlock.
*
* The requirements of the group lock are:
*
* - must satisfy all the functions above
* - must allow members to join or leave the group (for example,
* transaction may be added or removed from a dialog)
* - must be able to synchronize with external lock (for example, a dialog
* lock must be able to sync itself with PJSUA lock)
*
* Please see https://trac.pjsip.org/repos/wiki/Group_Lock for more info.
*/
/**
* Settings for creating the group lock.
*/
typedef struct pj_grp_lock_config
{
/**
* Creation flags, currently must be zero.
*/
unsigned flags;
} pj_grp_lock_config;
/**
* The group lock destroy handler, a destructor function called when
* a group lock is about to be destroyed.
*
* @param member A pointer to be passed to the handler.
*/
typedef void (*pj_grp_lock_handler)(void *member);
/**
* Initialize the config with the default values.
*
* @param cfg The config to be initialized.
*/
PJ_DECL(void) pj_grp_lock_config_default(pj_grp_lock_config *cfg);
/**
* Create a group lock object. Initially the group lock will have reference
* counter of zero.
*
* @param pool The group lock only uses the pool parameter to get
* the pool factory, from which it will create its own
* pool.
* @param cfg Optional configuration.
* @param p_grp_lock Pointer to receive the newly created group lock.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_create(pj_pool_t *pool,
const pj_grp_lock_config *cfg,
pj_grp_lock_t **p_grp_lock);
/**
* Create a group lock object, with the specified destructor handler, to be
* called by the group lock when it is about to be destroyed. Initially the
* group lock will have reference counter of zero.
*
* @param pool The group lock only uses the pool parameter to get
* the pool factory, from which it will create its own
* pool.
* @param cfg Optional configuration.
* @param member A pointer to be passed to the handler.
* @param handler The destroy handler.
* @param p_grp_lock Pointer to receive the newly created group lock.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_create_w_handler(pj_pool_t *pool,
const pj_grp_lock_config *cfg,
void *member,
pj_grp_lock_handler handler,
pj_grp_lock_t **p_grp_lock);
/**
* Forcibly destroy the group lock, ignoring the reference counter value.
*
* @param grp_lock The group lock.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_destroy( pj_grp_lock_t *grp_lock);
/**
* Move the contents of the old lock to the new lock and destroy the
* old lock.
*
* @param old_lock The old group lock to be destroyed.
* @param new_lock The new group lock.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_replace(pj_grp_lock_t *old_lock,
pj_grp_lock_t *new_lock);
/**
* Acquire lock on the specified group lock.
*
* @param grp_lock The group lock.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_acquire( pj_grp_lock_t *grp_lock);
/**
* Acquire lock on the specified group lock if it is available, otherwise
* return immediately wihout waiting.
*
* @param grp_lock The group lock.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_tryacquire( pj_grp_lock_t *grp_lock);
/**
* Release the previously held lock. This may cause the group lock
* to be destroyed if it is the last one to hold the reference counter.
* In that case, the function will return PJ_EGONE.
*
* @param grp_lock The group lock.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_release( pj_grp_lock_t *grp_lock);
/**
* Add a destructor handler, to be called by the group lock when it is
* about to be destroyed.
*
* @param grp_lock The group lock.
* @param pool Pool to allocate memory for the handler.
* @param member A pointer to be passed to the handler.
* @param handler The destroy handler.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_add_handler(pj_grp_lock_t *grp_lock,
pj_pool_t *pool,
void *member,
pj_grp_lock_handler handler);
/**
* Remove previously registered handler. All parameters must be the same
* as when the handler was added.
*
* @param grp_lock The group lock.
* @param member A pointer to be passed to the handler.
* @param handler The destroy handler.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_del_handler(pj_grp_lock_t *grp_lock,
void *member,
pj_grp_lock_handler handler);
/**
* Increment reference counter to prevent the group lock grom being destroyed.
*
* @param grp_lock The group lock.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
#if !PJ_GRP_LOCK_DEBUG
PJ_DECL(pj_status_t) pj_grp_lock_add_ref(pj_grp_lock_t *grp_lock);
/**
* Debug version of pj_grp_lock_add_ref(), allowing to specify file and lineno.
*
* @param grp_lock The group lock.
* @param x Filename
* @param y Line number
*
* @return PJ_SUCCESS or the appropriate error code.
*/
#define pj_grp_lock_add_ref_dbg(grp_lock, x, y) pj_grp_lock_add_ref(grp_lock)
#else
#define pj_grp_lock_add_ref(g) pj_grp_lock_add_ref_dbg(g, __FILE__, __LINE__)
PJ_DECL(pj_status_t) pj_grp_lock_add_ref_dbg(pj_grp_lock_t *grp_lock,
const char *file,
int line);
#endif
/**
* Decrement the reference counter. When the counter value reaches zero, the
* group lock will be destroyed and all destructor handlers will be called.
*
* @param grp_lock The group lock.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
#if !PJ_GRP_LOCK_DEBUG
PJ_DECL(pj_status_t) pj_grp_lock_dec_ref(pj_grp_lock_t *grp_lock);
/**
* Debug version of pj_grp_lock_dec_ref(), allowing to specify file and lineno.
*
* @param grp_lock The group lock.
* @param x Filename
* @param y Line number
*
* @return PJ_SUCCESS or the appropriate error code.
*/
#define pj_grp_lock_dec_ref_dbg(grp_lock, x, y) pj_grp_lock_dec_ref(grp_lock)
#else
#define pj_grp_lock_dec_ref(g) pj_grp_lock_dec_ref_dbg(g, __FILE__, __LINE__)
PJ_DECL(pj_status_t) pj_grp_lock_dec_ref_dbg(pj_grp_lock_t *grp_lock,
const char *file,
int line);
#endif
/**
* Get current reference count value. This normally is only used for
* debugging purpose.
*
* @param grp_lock The group lock.
*
* @return The reference count value.
*/
PJ_DECL(int) pj_grp_lock_get_ref(pj_grp_lock_t *grp_lock);
/**
* Dump group lock info for debugging purpose. If group lock debugging is
* enabled (via PJ_GRP_LOCK_DEBUG) macro, this will print the group lock
* reference counter value along with the source file and line. If
* debugging is disabled, this will only print the reference counter.
*
* @param grp_lock The group lock.
*/
PJ_DECL(void) pj_grp_lock_dump(pj_grp_lock_t *grp_lock);
/**
* Synchronize an external lock with the group lock, by adding it to the
* list of locks to be acquired by the group lock when the group lock is
* acquired.
*
* The ''pos'' argument specifies the lock order and also the relative
* position with regard to lock ordering against the group lock. Locks with
* lower ''pos'' value will be locked first, and those with negative value
* will be locked before the group lock (the group lock's ''pos'' value is
* zero).
*
* @param grp_lock The group lock.
* @param ext_lock The external lock
* @param pos The position.
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_chain_lock(pj_grp_lock_t *grp_lock,
pj_lock_t *ext_lock,
int pos);
/**
* Remove an external lock from group lock's list of synchronized locks.
*
* @param grp_lock The group lock.
* @param ext_lock The external lock
*
* @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_grp_lock_unchain_lock(pj_grp_lock_t *grp_lock,
pj_lock_t *ext_lock);
/** @} */
PJ_END_DECL
#endif /* __PJ_LOCK_H__ */

View File

@@ -0,0 +1,487 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_LOG_H__
#define __PJ_LOG_H__
/**
* @file log.h
* @brief Logging Utility.
*/
#include <pj/types.h>
#include <stdarg.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_MISC Miscelaneous
*/
/**
* @defgroup PJ_LOG Logging Facility
* @ingroup PJ_MISC
* @{
*
* The PJLIB logging facility is a configurable, flexible, and convenient
* way to write logging or trace information.
*
* To write to the log, one uses construct like below:
*
* <pre>
* ...
* PJ_LOG(3, ("main.c", "Starting hello..."));
* ...
* PJ_LOG(3, ("main.c", "Hello world from process %d", pj_getpid()));
* ...
* </pre>
*
* In the above example, the number @b 3 controls the verbosity level of
* the information (which means "information", by convention). The string
* "main.c" specifies the source or sender of the message.
*
*
* \section pj_log_quick_sample_sec Examples
*
* For examples, see:
* - Simple Log sample: \src{pjlib/src/pjlib-samples/log.c}
*
*/
/**
* Log decoration flag, to be specified with #pj_log_set_decor().
*/
enum pj_log_decoration
{
PJ_LOG_HAS_DAY_NAME = 1, /**< Include day name [default: no] */
PJ_LOG_HAS_YEAR = 2, /**< Include year digit [no] */
PJ_LOG_HAS_MONTH = 4, /**< Include month [no] */
PJ_LOG_HAS_DAY_OF_MON = 8, /**< Include day of month [no] */
PJ_LOG_HAS_TIME = 16, /**< Include time [yes] */
PJ_LOG_HAS_MICRO_SEC = 32, /**< Include microseconds [yes] */
PJ_LOG_HAS_SENDER = 64, /**< Include sender in the log [yes] */
PJ_LOG_HAS_NEWLINE = 128, /**< Terminate each call with newline [yes] */
PJ_LOG_HAS_CR = 256, /**< Include carriage return [no] */
PJ_LOG_HAS_SPACE = 512, /**< Include two spaces before log [yes] */
PJ_LOG_HAS_COLOR = 1024, /**< Colorize logs [yes on win32] */
PJ_LOG_HAS_LEVEL_TEXT = 2048, /**< Include level text string [no] */
PJ_LOG_HAS_THREAD_ID = 4096, /**< Include thread identification [no] */
PJ_LOG_HAS_THREAD_SWC = 8192, /**< Add mark when thread has switched [yes]*/
PJ_LOG_HAS_INDENT =16384 /**< Indentation. Say yes! [yes] */
};
/**
* Write log message.
* This is the main macro used to write text to the logging backend.
*
* @param level The logging verbosity level. Lower number indicates higher
* importance, with level zero indicates fatal error. Only
* numeral argument is permitted (e.g. not variable).
* @param arg Enclosed 'printf' like arguments, with the first
* argument is the sender, the second argument is format
* string and the following arguments are variable number of
* arguments suitable for the format string.
*
* Sample:
* \verbatim
PJ_LOG(2, (__FILE__, "current value is %d", value));
\endverbatim
* @hideinitializer
*/
#define PJ_LOG(level,arg) do { \
if (level <= pj_log_get_level()) { \
pj_log_wrapper_##level(arg); \
} \
} while (0)
/**
* Signature for function to be registered to the logging subsystem to
* write the actual log message to some output device.
*
* @param level Log level.
* @param data Log message, which will be NULL terminated.
* @param len Message length.
*/
typedef void pj_log_func(int level, const char *data, int len);
/**
* Default logging writer function used by front end logger function.
* This function will print the log message to stdout only.
* Application normally should NOT need to call this function, but
* rather use the PJ_LOG macro.
*
* @param level Log level.
* @param buffer Log message.
* @param len Message length.
*/
PJ_DECL(void) pj_log_write(int level, const char *buffer, int len);
#if PJ_LOG_MAX_LEVEL >= 1
/**
* Write to log.
*
* @param sender Source of the message.
* @param level Verbosity level.
* @param format Format.
* @param marker Marker.
*/
PJ_DECL(void) pj_log(const char *sender, int level,
const char *format, va_list marker);
/**
* Change log output function. The front-end logging functions will call
* this function to write the actual message to the desired device.
* By default, the front-end functions use pj_log_write() to write
* the messages, unless it's changed by calling this function.
*
* @param func The function that will be called to write the log
* messages to the desired device.
*/
PJ_DECL(void) pj_log_set_log_func( pj_log_func *func );
/**
* Get the current log output function that is used to write log messages.
*
* @return Current log output function.
*/
PJ_DECL(pj_log_func*) pj_log_get_log_func(void);
/**
* Set maximum log level. Application can call this function to set
* the desired level of verbosity of the logging messages. The bigger the
* value, the more verbose the logging messages will be printed. However,
* the maximum level of verbosity can not exceed compile time value of
* PJ_LOG_MAX_LEVEL.
*
* @param level The maximum level of verbosity of the logging
* messages (6=very detailed..1=error only, 0=disabled)
*/
PJ_DECL(void) pj_log_set_level(int level);
/**
* Get current maximum log verbositylevel.
*
* @return Current log maximum level.
*/
#if 1
PJ_DECL(int) pj_log_get_level(void);
#else
PJ_DECL_DATA(int) pj_log_max_level;
#define pj_log_get_level() pj_log_max_level
#endif
/**
* Set log decoration. The log decoration flag controls what are printed
* to output device alongside the actual message. For example, application
* can specify that date/time information should be displayed with each
* log message.
*
* @param decor Bitmask combination of #pj_log_decoration to control
* the layout of the log message.
*/
PJ_DECL(void) pj_log_set_decor(unsigned decor);
/**
* Get current log decoration flag.
*
* @return Log decoration flag.
*/
PJ_DECL(unsigned) pj_log_get_decor(void);
/**
* Add indentation to log message. Indentation will add PJ_LOG_INDENT_CHAR
* before the message, and is useful to show the depth of function calls.
*
* @param indent The indentation to add or substract. Positive value
* adds current indent, negative value subtracts current
* indent.
*/
PJ_DECL(void) pj_log_add_indent(int indent);
/**
* Set indentation to specific value.
*
* @param indent The indentation value.
*/
PJ_DECL(void) pj_log_set_indent(int indent);
/**
* Get current indentation value.
*
* @return Current indentation value.
*/
PJ_DECL(int) pj_log_get_indent(void);
/**
* Push indentation to the right by default value (PJ_LOG_INDENT_SIZE).
*/
PJ_DECL(void) pj_log_push_indent(void);
/**
* Pop indentation (to the left) by default value (PJ_LOG_INDENT_SIZE).
*/
PJ_DECL(void) pj_log_pop_indent(void);
/**
* Set color of log messages.
*
* @param level Log level which color will be changed.
* @param color Desired color.
*/
PJ_DECL(void) pj_log_set_color(int level, pj_color_t color);
/**
* Get color of log messages.
*
* @param level Log level which color will be returned.
* @return Log color.
*/
PJ_DECL(pj_color_t) pj_log_get_color(int level);
/**
* Internal function to be called by pj_init()
*/
pj_status_t pj_log_init(void);
#else /* #if PJ_LOG_MAX_LEVEL >= 1 */
/**
* Change log output function. The front-end logging functions will call
* this function to write the actual message to the desired device.
* By default, the front-end functions use pj_log_write() to write
* the messages, unless it's changed by calling this function.
*
* @param func The function that will be called to write the log
* messages to the desired device.
*/
# define pj_log_set_log_func(func)
/**
* Write to log.
*
* @param sender Source of the message.
* @param level Verbosity level.
* @param format Format.
* @param marker Marker.
*/
# define pj_log(sender, level, format, marker)
/**
* Set maximum log level. Application can call this function to set
* the desired level of verbosity of the logging messages. The bigger the
* value, the more verbose the logging messages will be printed. However,
* the maximum level of verbosity can not exceed compile time value of
* PJ_LOG_MAX_LEVEL.
*
* @param level The maximum level of verbosity of the logging
* messages (6=very detailed..1=error only, 0=disabled)
*/
# define pj_log_set_level(level)
/**
* Set log decoration. The log decoration flag controls what are printed
* to output device alongside the actual message. For example, application
* can specify that date/time information should be displayed with each
* log message.
*
* @param decor Bitmask combination of #pj_log_decoration to control
* the layout of the log message.
*/
# define pj_log_set_decor(decor)
/**
* Add indentation to log message. Indentation will add PJ_LOG_INDENT_CHAR
* before the message, and is useful to show the depth of function calls.
*
* @param indent The indentation to add or substract. Positive value
* adds current indent, negative value subtracts current
* indent.
*/
# define pj_log_add_indent(indent)
/**
* Set indentation to specific value.
*
* @param indent The indentation value.
*/
# define pj_log_set_indent(indent)
/**
* Get current indentation value.
*
* @return Current indentation value.
*/
# define pj_log_get_indent() 0
/**
* Push indentation to the right by default value (PJ_LOG_INDENT_SIZE).
*/
# define pj_log_push_indent()
/**
* Pop indentation (to the left) by default value (PJ_LOG_INDENT_SIZE).
*/
# define pj_log_pop_indent()
/**
* Set color of log messages.
*
* @param level Log level which color will be changed.
* @param color Desired color.
*/
# define pj_log_set_color(level, color)
/**
* Get current maximum log verbositylevel.
*
* @return Current log maximum level.
*/
# define pj_log_get_level() 0
/**
* Get current log decoration flag.
*
* @return Log decoration flag.
*/
# define pj_log_get_decor() 0
/**
* Get color of log messages.
*
* @param level Log level which color will be returned.
* @return Log color.
*/
# define pj_log_get_color(level) 0
/**
* Internal.
*/
# define pj_log_init() PJ_SUCCESS
#endif /* #if PJ_LOG_MAX_LEVEL >= 1 */
/**
* @}
*/
/* **************************************************************************/
/*
* Log functions implementation prototypes.
* These functions are called by PJ_LOG macros according to verbosity
* level specified when calling the macro. Applications should not normally
* need to call these functions directly.
*/
/**
* @def pj_log_wrapper_1(arg)
* Internal function to write log with verbosity 1. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 1.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 1
#define pj_log_wrapper_1(arg) pj_log_1 arg
/** Internal function. */
PJ_DECL(void) pj_log_1(const char *src, const char *format, ...)
PJ_PRINT_FUNC_DECOR(2);
#else
#define pj_log_wrapper_1(arg)
#endif
/**
* @def pj_log_wrapper_2(arg)
* Internal function to write log with verbosity 2. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 2.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 2
#define pj_log_wrapper_2(arg) pj_log_2 arg
/** Internal function. */
PJ_DECL(void) pj_log_2(const char *src, const char *format, ...)
PJ_PRINT_FUNC_DECOR(2);
#else
#define pj_log_wrapper_2(arg)
#endif
/**
* @def pj_log_wrapper_3(arg)
* Internal function to write log with verbosity 3. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 3.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 3
#define pj_log_wrapper_3(arg) pj_log_3 arg
/** Internal function. */
PJ_DECL(void) pj_log_3(const char *src, const char *format, ...)
PJ_PRINT_FUNC_DECOR(2);
#else
#define pj_log_wrapper_3(arg)
#endif
/**
* @def pj_log_wrapper_4(arg)
* Internal function to write log with verbosity 4. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 4.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 4
#define pj_log_wrapper_4(arg) pj_log_4 arg
/** Internal function. */
PJ_DECL(void) pj_log_4(const char *src, const char *format, ...)
PJ_PRINT_FUNC_DECOR(2);
#else
#define pj_log_wrapper_4(arg)
#endif
/**
* @def pj_log_wrapper_5(arg)
* Internal function to write log with verbosity 5. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 5.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 5
#define pj_log_wrapper_5(arg) pj_log_5 arg
/** Internal function. */
PJ_DECL(void) pj_log_5(const char *src, const char *format, ...)
PJ_PRINT_FUNC_DECOR(2);
#else
#define pj_log_wrapper_5(arg)
#endif
/**
* @def pj_log_wrapper_6(arg)
* Internal function to write log with verbosity 6. Will evaluate to
* empty expression if PJ_LOG_MAX_LEVEL is below 6.
* @param arg Log expression.
*/
#if PJ_LOG_MAX_LEVEL >= 6
#define pj_log_wrapper_6(arg) pj_log_6 arg
/** Internal function. */
PJ_DECL(void) pj_log_6(const char *src, const char *format, ...)
PJ_PRINT_FUNC_DECOR(2);
#else
#define pj_log_wrapper_6(arg)
#endif
PJ_END_DECL
#endif /* __PJ_LOG_H__ */

View File

@@ -0,0 +1,203 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_MATH_H__
#define __PJ_MATH_H__
/**
* @file math.h
* @brief Mathematics and Statistics.
*/
#include <pj/string.h>
#include <pj/compat/high_precision.h>
PJ_BEGIN_DECL
/**
* @defgroup pj_math Mathematics and Statistics
* @ingroup PJ_MISC
* @{
*
* Provides common mathematics constants and operations, and also standard
* statistics calculation (min, max, mean, standard deviation). Statistics
* calculation is done in realtime (statistics state is updated on time each
* new sample comes).
*/
/**
* Mathematical constants
*/
/** pi */
#define PJ_PI 3.14159265358979323846 /* pi */
/** 1/pi */
#define PJ_1_PI 0.318309886183790671538 /* 1/pi */
/**
* Mathematical macros
*/
/** Get the absolute value */
#define PJ_ABS(x) ((x) > 0 ? (x) : -(x))
/** Get the maximum of two values */
#define PJ_MAX(x, y) ((x) > (y)? (x) : (y))
/** Get the minimum of two values */
#define PJ_MIN(x, y) ((x) < (y)? (x) : (y))
/**
* This structure describes statistics state.
*/
typedef struct pj_math_stat
{
int n; /**< number of samples */
int max; /**< maximum value */
int min; /**< minimum value */
int last; /**< last value */
int mean; /**< mean */
/* Private members */
#if PJ_HAS_FLOATING_POINT
float fmean_; /**< mean(floating point) */
#else
int mean_res_; /**< mean residue */
#endif
pj_highprec_t m2_; /**< variance * n */
} pj_math_stat;
/**
* Calculate integer square root of an integer.
*
* @param i Integer to be calculated.
*
* @return Square root result.
*/
PJ_INLINE(unsigned) pj_isqrt(unsigned i)
{
unsigned res = 1, prev;
/* Rough guess, calculate half bit of input */
prev = i >> 2;
while (prev) {
prev >>= 2;
res <<= 1;
}
/* Babilonian method */
do {
prev = res;
res = (prev + i/prev) >> 1;
} while ((prev+res)>>1 != res);
return res;
}
/**
* Initialize statistics state.
*
* @param stat Statistic state.
*/
PJ_INLINE(void) pj_math_stat_init(pj_math_stat *stat)
{
pj_bzero(stat, sizeof(pj_math_stat));
}
/**
* Update statistics state as a new sample comes.
*
* @param stat Statistic state.
* @param val The new sample data.
*/
PJ_INLINE(void) pj_math_stat_update(pj_math_stat *stat, int val)
{
#if PJ_HAS_FLOATING_POINT
float delta;
#else
int delta;
#endif
stat->last = val;
if (stat->n++) {
if (stat->min > val)
stat->min = val;
if (stat->max < val)
stat->max = val;
} else {
stat->min = stat->max = val;
}
#if PJ_HAS_FLOATING_POINT
delta = val - stat->fmean_;
stat->fmean_ += delta/stat->n;
/* Return mean value with 'rounding' */
stat->mean = (int) (stat->fmean_ + 0.5);
stat->m2_ += (int)(delta * (val-stat->fmean_));
#else
delta = val - stat->mean;
stat->mean += delta/stat->n;
stat->mean_res_ += delta % stat->n;
if (stat->mean_res_ >= stat->n) {
++stat->mean;
stat->mean_res_ -= stat->n;
} else if (stat->mean_res_ <= -stat->n) {
--stat->mean;
stat->mean_res_ += stat->n;
}
stat->m2_ += delta * (val-stat->mean);
#endif
}
/**
* Get the standard deviation of specified statistics state.
*
* @param stat Statistic state.
*
* @return The standard deviation.
*/
PJ_INLINE(unsigned) pj_math_stat_get_stddev(const pj_math_stat *stat)
{
if (stat->n == 0) return 0;
return (pj_isqrt((unsigned)(stat->m2_/stat->n)));
}
/**
* Set the standard deviation of statistics state. This is useful when
* the statistic state is operated in 'read-only' mode as a storage of
* statistical data.
*
* @param stat Statistic state.
*
* @param dev The standard deviation.
*/
PJ_INLINE(void) pj_math_stat_set_stddev(pj_math_stat *stat, unsigned dev)
{
if (stat->n == 0)
stat->n = 1;
stat->m2_ = dev*dev*stat->n;
}
/** @} */
PJ_END_DECL
#endif /* __PJ_MATH_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,918 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pj/list.h>
/* See if we use pool's alternate API.
* The alternate API is used e.g. to implement pool debugging.
*/
#if PJ_HAS_POOL_ALT_API
# include <pj/pool_alt.h>
#endif
#ifndef __PJ_POOL_H__
#define __PJ_POOL_H__
/**
* @file pool.h
* @brief Memory Pool.
*/
PJ_BEGIN_DECL
/**
* @defgroup PJ_POOL_GROUP Fast Memory Pool
* @brief
* Memory pools allow dynamic memory allocation comparable to malloc or the
* new in operator C++. Those implementations are not desirable for very
* high performance applications or real-time systems, because of the
* performance bottlenecks and it suffers from fragmentation issue.
*
* \section PJ_POOL_INTRO_SEC PJLIB's Memory Pool
* \subsection PJ_POOL_ADVANTAGE_SUBSEC Advantages
*
* PJLIB's pool has many advantages over traditional malloc/new operator and
* over other memory pool implementations, because:
* - unlike other memory pool implementation, it allows allocation of
* memory chunks of different sizes,
* - it's very very fast.
* \n
* Memory chunk allocation is not only an O(1)
* operation, but it's also very simple (just
* few pointer arithmetic operations) and it doesn't require locking
* any mutex,
* - it's memory efficient.
* \n
* Pool doesn't keep track individual memory chunks allocated by
* applications, so there is no additional overhead needed for each
* memory allocation (other than possible additional of few bytes, up to
* PJ_POOL_ALIGNMENT-1, for aligning the memory).
* But see the @ref PJ_POOL_CAVEATS_SUBSEC below.
* - it prevents memory leaks.
* \n
* Memory pool inherently has garbage collection functionality. In fact,
* there is no need to free the chunks allocated from the memory pool.
* All chunks previously allocated from the pool will be freed once the
* pool itself is destroyed. This would prevent memory leaks that haunt
* programmers for decades, and it provides additional performance
* advantage over traditional malloc/new operator.
*
* Even more, PJLIB's memory pool provides some additional usability and
* flexibility for applications:
* - memory leaks are easily traceable, since memory pool is assigned name,
* and application can inspect what pools currently active in the system.
* - by design, memory allocation from a pool is not thread safe. We assumed
* that a pool will be owned by a higher level object, and thread safety
* should be handled by that object. This enables very fast pool operations
* and prevents unnecessary locking operations,
* - by default, the memory pool API behaves more like C++ new operator,
* in that it will throw PJ_NO_MEMORY_EXCEPTION exception (see
* @ref PJ_EXCEPT) when memory chunk allocation fails. This enables failure
* handling to be done on more high level function (instead of checking
* the result of pj_pool_alloc() everytime). If application doesn't like
* this, the default behavior can be changed on global basis by supplying
* different policy to the pool factory.
* - any memory allocation backend allocator/deallocator may be used. By
* default, the policy uses malloc() and free() to manage the pool's block,
* but application may use different strategy, for example to allocate
* memory blocks from a globally static memory location.
*
*
* \subsection PJ_POOL_PERFORMANCE_SUBSEC Performance
*
* The result of PJLIB's memory design and careful implementation is a
* memory allocation strategy that can speed-up the memory allocations
* and deallocations by up to <b>30 times</b> compared to standard
* malloc()/free() (more than 150 million allocations per second on a
* P4/3.0GHz Linux machine).
*
* (Note: your mileage may vary, of course. You can see how much PJLIB's
* pool improves the performance over malloc()/free() in your target
* system by running pjlib-test application).
*
*
* \subsection PJ_POOL_CAVEATS_SUBSEC Caveats
*
* There are some caveats though!
*
* When creating pool, PJLIB requires applications to specify the initial
* pool size, and as soon as the pool is created, PJLIB allocates memory
* from the system by that size. Application designers MUST choose the
* initial pool size carefully, since choosing too big value will result in
* wasting system's memory.
*
* But the pool can grow. Application designer can specify how the
* pool will grow in size, by specifying the size increment when creating
* the pool.
*
* The pool, however, <b>cannot</b> shrink! Since there is <b>no</b>
* function to deallocate memory chunks, there is no way for the pool to
* release back unused memory to the system.
* Application designers must be aware that constant memory allocations
* from pool that has infinite life-time may cause the memory usage of
* the application to grow over time.
*
*
* \section PJ_POOL_USING_SEC Using Memory Pool
*
* This section describes how to use PJLIB's memory pool framework.
* As we hope the readers will witness, PJLIB's memory pool API is quite
* straightforward.
*
* \subsection PJ_POOL_USING_F Create Pool Factory
* First, application needs to initialize a pool factory (this normally
* only needs to be done once in one application). PJLIB provides
* a pool factory implementation called caching pool (see @ref
* PJ_CACHING_POOL), and it is initialized by calling #pj_caching_pool_init().
*
* \subsection PJ_POOL_USING_P Create The Pool
* Then application creates the pool object itself with #pj_pool_create(),
* specifying among other thing the pool factory where the pool should
* be created from, the pool name, initial size, and increment/expansion
* size.
*
* \subsection PJ_POOL_USING_M Allocate Memory as Required
* Then whenever application needs to allocate dynamic memory, it would
* call #pj_pool_alloc(), #pj_pool_calloc(), or #pj_pool_zalloc() to
* allocate memory chunks from the pool.
*
* \subsection PJ_POOL_USING_DP Destroy the Pool
* When application has finished with the pool, it should call
* #pj_pool_release() to release the pool object back to the factory.
* Depending on the types of the factory, this may release the memory back
* to the operating system.
*
* \subsection PJ_POOL_USING_Dc Destroy the Pool Factory
* And finally, before application quites, it should deinitialize the
* pool factory, to make sure that all memory blocks allocated by the
* factory are released back to the operating system. After this, of
* course no more memory pool allocation can be requested.
*
* \subsection PJ_POOL_USING_EX Example
* Below is a sample complete program that utilizes PJLIB's memory pool.
*
* \code
#include <pjlib.h>
#define THIS_FILE "pool_sample.c"
static void my_perror(const char *title, pj_status_t status)
{
PJ_PERROR(1,(THIS_FILE, status, title));
}
static void pool_demo_1(pj_pool_factory *pfactory)
{
unsigned i;
pj_pool_t *pool;
// Must create pool before we can allocate anything
pool = pj_pool_create(pfactory, // the factory
"pool1", // pool's name
4000, // initial size
4000, // increment size
NULL); // use default callback.
if (pool == NULL) {
my_perror("Error creating pool", PJ_ENOMEM);
return;
}
// Demo: allocate some memory chunks
for (i=0; i<1000; ++i) {
void *p;
p = pj_pool_alloc(pool, (pj_rand()+1) % 512);
// Do something with p
...
// Look! No need to free p!!
}
// Done with silly demo, must free pool to release all memory.
pj_pool_release(pool);
}
int main()
{
pj_caching_pool cp;
pj_status_t status;
// Must init PJLIB before anything else
status = pj_init();
if (status != PJ_SUCCESS) {
my_perror("Error initializing PJLIB", status);
return 1;
}
// Create the pool factory, in this case, a caching pool,
// using default pool policy.
pj_caching_pool_init(&cp, NULL, 1024*1024 );
// Do a demo
pool_demo_1(&cp.factory);
// Done with demos, destroy caching pool before exiting app.
pj_caching_pool_destroy(&cp);
return 0;
}
\endcode
*
* More information about pool factory, the pool object, and caching pool
* can be found on the Module Links below.
*/
/**
* @defgroup PJ_POOL Memory Pool Object
* @ingroup PJ_POOL_GROUP
* @brief
* The memory pool is an opaque object created by pool factory.
* Application uses this object to request a memory chunk, by calling
* #pj_pool_alloc(), #pj_pool_calloc(), or #pj_pool_zalloc().
* When the application has finished using
* the pool, it must call #pj_pool_release() to free all the chunks previously
* allocated and release the pool back to the factory.
*
* A memory pool is initialized with an initial amount of memory, which is
* called a block. Pool can be configured to dynamically allocate more memory
* blocks when it runs out of memory.
*
* The pool doesn't keep track of individual memory allocations
* by user, and the user doesn't have to free these indidual allocations. This
* makes memory allocation simple and very fast. All the memory allocated from
* the pool will be destroyed when the pool itself is destroyed.
*
* \section PJ_POOL_THREADING_SEC More on Threading Policies
* - By design, memory allocation from a pool is not thread safe. We assumed
* that a pool will be owned by an object, and thread safety should be
* handled by that object. Thus these functions are not thread safe:
* - #pj_pool_alloc,
* - #pj_pool_calloc,
* - and other pool statistic functions.
* - Threading in the pool factory is decided by the policy set for the
* factory when it was created.
*
* \section PJ_POOL_EXAMPLES_SEC Examples
*
* For some sample codes on how to use the pool, please see:
* - Pool test: \src{pjlib/src/pjlib-test/pool.c}
*
* @{
*/
/**
* The type for function to receive callback from the pool when it is unable
* to allocate memory. The elegant way to handle this condition is to throw
* exception, and this is what is expected by most of this library
* components.
*/
typedef void pj_pool_callback(pj_pool_t *pool, pj_size_t size);
/**
* This class, which is used internally by the pool, describes a single
* block of memory from which user memory allocations will be allocated from.
*/
typedef struct pj_pool_block
{
PJ_DECL_LIST_MEMBER(struct pj_pool_block); /**< List's prev and next. */
unsigned char *buf; /**< Start of buffer. */
unsigned char *cur; /**< Current alloc ptr. */
unsigned char *end; /**< End of buffer. */
} pj_pool_block;
/**
* This structure describes the memory pool. Only implementors of pool factory
* need to care about the contents of this structure.
*/
struct pj_pool_t
{
PJ_DECL_LIST_MEMBER(struct pj_pool_t); /**< Standard list elements. */
/** Pool name */
char obj_name[PJ_MAX_OBJ_NAME];
/** Pool factory. */
pj_pool_factory *factory;
/** Data put by factory */
void *factory_data;
/** Current capacity allocated by the pool. */
pj_size_t capacity;
/** Size of memory block to be allocated when the pool runs out of memory */
pj_size_t increment_size;
/** List of memory blocks allcoated by the pool. */
pj_pool_block block_list;
/** The callback to be called when the pool is unable to allocate memory. */
pj_pool_callback *callback;
};
/**
* Guidance on how much memory required for initial pool administrative data.
*/
#define PJ_POOL_SIZE (sizeof(struct pj_pool_t))
/**
* Pool memory alignment (must be power of 2).
*/
#ifndef PJ_POOL_ALIGNMENT
# define PJ_POOL_ALIGNMENT 4
#endif
/**
* Create a new pool from the pool factory. This wrapper will call create_pool
* member of the pool factory.
*
* @param factory The pool factory.
* @param name The name to be assigned to the pool. The name should
* not be longer than PJ_MAX_OBJ_NAME (32 chars), or
* otherwise it will be truncated.
* @param initial_size The size of initial memory blocks taken by the pool.
* Note that the pool will take 68+20 bytes for
* administrative area from this block.
* @param increment_size the size of each additional blocks to be allocated
* when the pool is running out of memory. If user
* requests memory which is larger than this size, then
* an error occurs.
* Note that each time a pool allocates additional block,
* it needs PJ_POOL_SIZE more to store some
* administrative info.
* @param callback Callback to be called when error occurs in the pool.
* If this value is NULL, then the callback from pool
* factory policy will be used.
* Note that when an error occurs during pool creation,
* the callback itself is not called. Instead, NULL
* will be returned.
*
* @return The memory pool, or NULL.
*/
PJ_IDECL(pj_pool_t*) pj_pool_create(pj_pool_factory *factory,
const char *name,
pj_size_t initial_size,
pj_size_t increment_size,
pj_pool_callback *callback);
/**
* Release the pool back to pool factory.
*
* @param pool Memory pool.
*/
PJ_IDECL(void) pj_pool_release( pj_pool_t *pool );
/**
* Release the pool back to pool factory and set the pool pointer to zero.
*
* @param ppool Pointer to memory pool.
*/
PJ_IDECL(void) pj_pool_safe_release( pj_pool_t **ppool );
/**
* Release the pool back to pool factory and set the pool pointer to zero.
* The memory pool content will be wiped out first before released.
*
* @param ppool Pointer to memory pool.
*/
PJ_IDECL(void) pj_pool_secure_release( pj_pool_t **ppool );
/**
* Get pool object name.
*
* @param pool the pool.
*
* @return pool name as NULL terminated string.
*/
PJ_IDECL(const char *) pj_pool_getobjname( const pj_pool_t *pool );
/**
* Reset the pool to its state when it was initialized.
* This means that if additional blocks have been allocated during runtime,
* then they will be freed. Only the original block allocated during
* initialization is retained. This function will also reset the internal
* counters, such as pool capacity and used size.
*
* @param pool the pool.
*/
PJ_DECL(void) pj_pool_reset( pj_pool_t *pool );
/**
* Get the pool capacity, that is, the system storage that have been allocated
* by the pool, and have been used/will be used to allocate user requests.
* There's no guarantee that the returned value represent a single
* contiguous block, because the capacity may be spread in several blocks.
*
* @param pool the pool.
*
* @return the capacity.
*/
PJ_IDECL(pj_size_t) pj_pool_get_capacity( pj_pool_t *pool );
/**
* Get the total size of user allocation request.
*
* @param pool the pool.
*
* @return the total size.
*/
PJ_IDECL(pj_size_t) pj_pool_get_used_size( pj_pool_t *pool );
/**
* Allocate storage with the specified size from the pool.
* If there's no storage available in the pool, then the pool can allocate more
* blocks if the increment size is larger than the requested size.
*
* @param pool the pool.
* @param size the requested size.
*
* @return pointer to the allocated memory.
*
* @see PJ_POOL_ALLOC_T
*/
PJ_IDECL(void*) pj_pool_alloc( pj_pool_t *pool, pj_size_t size);
/**
* Allocate storage from the pool, and initialize it to zero.
* This function behaves like pj_pool_alloc(), except that the storage will
* be initialized to zero.
*
* @param pool the pool.
* @param count the number of elements in the array.
* @param elem the size of individual element.
*
* @return pointer to the allocated memory.
*/
PJ_IDECL(void*) pj_pool_calloc( pj_pool_t *pool, pj_size_t count,
pj_size_t elem);
/**
* Allocate storage from the pool and initialize it to zero.
*
* @param pool The pool.
* @param size The size to be allocated.
*
* @return Pointer to the allocated memory.
*
* @see PJ_POOL_ZALLOC_T
*/
PJ_INLINE(void*) pj_pool_zalloc(pj_pool_t *pool, pj_size_t size)
{
return pj_pool_calloc(pool, 1, size);
}
/**
* This macro allocates memory from the pool and returns the instance of
* the specified type. It provides a stricker type safety than pj_pool_alloc()
* since the return value of this macro will be type-casted to the specified
* type.
*
* @param pool The pool
* @param type The type of object to be allocated
*
* @return Memory buffer of the specified type.
*/
#define PJ_POOL_ALLOC_T(pool,type) \
((type*)pj_pool_alloc(pool, sizeof(type)))
/**
* This macro allocates memory from the pool, zeroes the buffer, and
* returns the instance of the specified type. It provides a stricker type
* safety than pj_pool_zalloc() since the return value of this macro will be
* type-casted to the specified type.
*
* @param pool The pool
* @param type The type of object to be allocated
*
* @return Memory buffer of the specified type.
*/
#define PJ_POOL_ZALLOC_T(pool,type) \
((type*)pj_pool_zalloc(pool, sizeof(type)))
/*
* Internal functions
*/
/** Internal function */
PJ_IDECL(void*) pj_pool_alloc_from_block(pj_pool_block *block, pj_size_t size);
/** Internal function */
PJ_DECL(void*) pj_pool_allocate_find(pj_pool_t *pool, pj_size_t size);
/**
* @} // PJ_POOL
*/
/* **************************************************************************/
/**
* @defgroup PJ_POOL_FACTORY Pool Factory and Policy
* @ingroup PJ_POOL_GROUP
* @brief
* A pool object must be created through a factory. A factory not only provides
* generic interface functions to create and release pool, but also provides
* strategy to manage the life time of pools. One sample implementation,
* \a pj_caching_pool, can be set to keep the pools released by application for
* future use as long as the total memory is below the limit.
*
* The pool factory interface declared in PJLIB is designed to be extensible.
* Application can define its own strategy by creating it's own pool factory
* implementation, and this strategy can be used even by existing library
* without recompilation.
*
* \section PJ_POOL_FACTORY_ITF Pool Factory Interface
* The pool factory defines the following interface:
* - \a policy: the memory pool factory policy.
* - \a create_pool(): create a new memory pool.
* - \a release_pool(): release memory pool back to factory.
*
* \section PJ_POOL_FACTORY_POL Pool Factory Policy.
*
* A pool factory only defines functions to create and release pool and how
* to manage pools, but the rest of the functionalities are controlled by
* policy. A pool policy defines:
* - how memory block is allocated and deallocated (the default implementation
* allocates and deallocate memory by calling malloc() and free()).
* - callback to be called when memory allocation inside a pool fails (the
* default implementation will throw PJ_NO_MEMORY_EXCEPTION exception).
* - concurrency when creating and releasing pool from/to the factory.
*
* A pool factory can be given different policy during creation to make
* it behave differently. For example, caching pool factory can be configured
* to allocate and deallocate from a static/contiguous/preallocated memory
* instead of using malloc()/free().
*
* What strategy/factory and what policy to use is not defined by PJLIB, but
* instead is left to application to make use whichever is most efficient for
* itself.
*
* The pool factory policy controls the behaviour of memory factories, and
* defines the following interface:
* - \a block_alloc(): allocate memory block from backend memory mgmt/system.
* - \a block_free(): free memory block back to backend memory mgmt/system.
* @{
*/
/* We unfortunately don't have support for factory policy options as now,
so we keep this commented at the moment.
enum PJ_POOL_FACTORY_OPTION
{
PJ_POOL_FACTORY_SERIALIZE = 1
};
*/
/**
* This structure declares pool factory interface.
*/
typedef struct pj_pool_factory_policy
{
/**
* Allocate memory block (for use by pool). This function is called
* by memory pool to allocate memory block.
*
* @param factory Pool factory.
* @param size The size of memory block to allocate.
*
* @return Memory block.
*/
void* (*block_alloc)(pj_pool_factory *factory, pj_size_t size);
/**
* Free memory block.
*
* @param factory Pool factory.
* @param mem Memory block previously allocated by block_alloc().
* @param size The size of memory block.
*/
void (*block_free)(pj_pool_factory *factory, void *mem, pj_size_t size);
/**
* Default callback to be called when memory allocation fails.
*/
pj_pool_callback *callback;
/**
* Option flags.
*/
unsigned flags;
} pj_pool_factory_policy;
/**
* This constant denotes the exception number that will be thrown by default
* memory factory policy when memory allocation fails.
*
* @see pj_NO_MEMORY_EXCEPTION()
*/
PJ_DECL_DATA(int) PJ_NO_MEMORY_EXCEPTION;
/**
* Get #PJ_NO_MEMORY_EXCEPTION constant.
*/
PJ_DECL(int) pj_NO_MEMORY_EXCEPTION(void);
/**
* This global variable points to default memory pool factory policy.
* The behaviour of the default policy is:
* - block allocation and deallocation use malloc() and free().
* - callback will raise PJ_NO_MEMORY_EXCEPTION exception.
* - access to pool factory is not serialized (i.e. not thread safe).
*
* @see pj_pool_factory_get_default_policy
*/
PJ_DECL_DATA(pj_pool_factory_policy) pj_pool_factory_default_policy;
/**
* Get the default pool factory policy.
*
* @return the pool policy.
*/
PJ_DECL(const pj_pool_factory_policy*) pj_pool_factory_get_default_policy(void);
/**
* This structure contains the declaration for pool factory interface.
*/
struct pj_pool_factory
{
/**
* Memory pool policy.
*/
pj_pool_factory_policy policy;
/**
* Create a new pool from the pool factory.
*
* @param factory The pool factory.
* @param name the name to be assigned to the pool. The name should
* not be longer than PJ_MAX_OBJ_NAME (32 chars), or
* otherwise it will be truncated.
* @param initial_size the size of initial memory blocks taken by the pool.
* Note that the pool will take 68+20 bytes for
* administrative area from this block.
* @param increment_size the size of each additional blocks to be allocated
* when the pool is running out of memory. If user
* requests memory which is larger than this size, then
* an error occurs.
* Note that each time a pool allocates additional block,
* it needs 20 bytes (equal to sizeof(pj_pool_block)) to
* store some administrative info.
* @param callback Cllback to be called when error occurs in the pool.
* Note that when an error occurs during pool creation,
* the callback itself is not called. Instead, NULL
* will be returned.
*
* @return the memory pool, or NULL.
*/
pj_pool_t* (*create_pool)( pj_pool_factory *factory,
const char *name,
pj_size_t initial_size,
pj_size_t increment_size,
pj_pool_callback *callback);
/**
* Release the pool to the pool factory.
*
* @param factory The pool factory.
* @param pool The pool to be released.
*/
void (*release_pool)( pj_pool_factory *factory, pj_pool_t *pool );
/**
* Dump pool status to log.
*
* @param factory The pool factory.
*/
void (*dump_status)( pj_pool_factory *factory, pj_bool_t detail );
/**
* This is optional callback to be called by allocation policy when
* it allocates a new memory block. The factory may use this callback
* for example to keep track of the total number of memory blocks
* currently allocated by applications.
*
* @param factory The pool factory.
* @param size Size requested by application.
*
* @return MUST return PJ_TRUE, otherwise the block
* allocation is cancelled.
*/
pj_bool_t (*on_block_alloc)(pj_pool_factory *factory, pj_size_t size);
/**
* This is optional callback to be called by allocation policy when
* it frees memory block. The factory may use this callback
* for example to keep track of the total number of memory blocks
* currently allocated by applications.
*
* @param factory The pool factory.
* @param size Size freed.
*/
void (*on_block_free)(pj_pool_factory *factory, pj_size_t size);
};
/**
* This function is intended to be used by pool factory implementors.
* @param factory Pool factory.
* @param name Pool name.
* @param initial_size Initial size.
* @param increment_size Increment size.
* @param callback Callback.
* @return The pool object, or NULL.
*/
PJ_DECL(pj_pool_t*) pj_pool_create_int( pj_pool_factory *factory,
const char *name,
pj_size_t initial_size,
pj_size_t increment_size,
pj_pool_callback *callback);
/**
* This function is intended to be used by pool factory implementors.
* @param pool The pool.
* @param name Pool name.
* @param increment_size Increment size.
* @param callback Callback function.
*/
PJ_DECL(void) pj_pool_init_int( pj_pool_t *pool,
const char *name,
pj_size_t increment_size,
pj_pool_callback *callback);
/**
* This function is intended to be used by pool factory implementors.
* @param pool The memory pool.
*/
PJ_DECL(void) pj_pool_destroy_int( pj_pool_t *pool );
/**
* Dump pool factory state.
* @param pf The pool factory.
* @param detail Detail state required.
*/
PJ_INLINE(void) pj_pool_factory_dump( pj_pool_factory *pf,
pj_bool_t detail )
{
(*pf->dump_status)(pf, detail);
}
/**
* @} // PJ_POOL_FACTORY
*/
/* **************************************************************************/
/**
* @defgroup PJ_CACHING_POOL Caching Pool Factory
* @ingroup PJ_POOL_GROUP
* @brief
* Caching pool is one sample implementation of pool factory where the
* factory can reuse memory to create a pool. Application defines what the
* maximum memory the factory can hold, and when a pool is released the
* factory decides whether to destroy the pool or to keep it for future use.
* If the total amount of memory in the internal cache is still within the
* limit, the factory will keep the pool in the internal cache, otherwise the
* pool will be destroyed, thus releasing the memory back to the system.
*
* @{
*/
/**
* Number of unique sizes, to be used as index to the free list.
* Each pool in the free list is organized by it's size.
*/
#define PJ_CACHING_POOL_ARRAY_SIZE 16
/**
* Declaration for caching pool. Application doesn't normally need to
* care about the contents of this struct, it is only provided here because
* application need to define an instance of this struct (we can not allocate
* the struct from a pool since there is no pool factory yet!).
*/
struct pj_caching_pool
{
/** Pool factory interface, must be declared first. */
pj_pool_factory factory;
/** Current factory's capacity, i.e. number of bytes that are allocated
* and available for application in this factory. The factory's
* capacity represents the size of all pools kept by this factory
* in it's free list, which will be returned to application when it
* requests to create a new pool.
*/
pj_size_t capacity;
/** Maximum size that can be held by this factory. Once the capacity
* has exceeded @a max_capacity, further #pj_pool_release() will
* flush the pool. If the capacity is still below the @a max_capacity,
* #pj_pool_release() will save the pool to the factory's free list.
*/
pj_size_t max_capacity;
/**
* Number of pools currently held by applications. This number gets
* incremented everytime #pj_pool_create() is called, and gets
* decremented when #pj_pool_release() is called.
*/
pj_size_t used_count;
/**
* Total size of memory currently used by application.
*/
pj_size_t used_size;
/**
* The maximum size of memory used by application throughout the life
* of the caching pool.
*/
pj_size_t peak_used_size;
/**
* Lists of pools in the cache, indexed by pool size.
*/
pj_list free_list[PJ_CACHING_POOL_ARRAY_SIZE];
/**
* List of pools currently allocated by applications.
*/
pj_list used_list;
/**
* Internal pool.
*/
char pool_buf[256 * (sizeof(size_t) / 4)];
/**
* Mutex.
*/
pj_lock_t *lock;
};
/**
* Initialize caching pool.
*
* @param ch_pool The caching pool factory to be initialized.
* @param policy Pool factory policy.
* @param max_capacity The total capacity to be retained in the cache. When
* the pool is returned to the cache, it will be kept in
* recycling list if the total capacity of pools in this
* list plus the capacity of the pool is still below this
* value.
*/
PJ_DECL(void) pj_caching_pool_init( pj_caching_pool *ch_pool,
const pj_pool_factory_policy *policy,
pj_size_t max_capacity);
/**
* Destroy caching pool, and release all the pools in the recycling list.
*
* @param ch_pool The caching pool.
*/
PJ_DECL(void) pj_caching_pool_destroy( pj_caching_pool *ch_pool );
/**
* @} // PJ_CACHING_POOL
*/
# if PJ_FUNCTIONS_ARE_INLINED
# include "pool_i.h"
# endif
PJ_END_DECL
#endif /* __PJ_POOL_H__ */

View File

@@ -0,0 +1,212 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_POOL_ALT_H__
#define __PJ_POOL_ALT_H__
#define __PJ_POOL_H__
PJ_BEGIN_DECL
/**
* The type for function to receive callback from the pool when it is unable
* to allocate memory. The elegant way to handle this condition is to throw
* exception, and this is what is expected by most of this library
* components.
*/
typedef void pj_pool_callback(pj_pool_t *pool, pj_size_t size);
struct pj_pool_mem
{
struct pj_pool_mem *next;
/* data follows immediately */
};
struct pj_pool_t
{
struct pj_pool_mem *first_mem;
pj_pool_factory *factory;
char obj_name[32];
pj_size_t used_size;
pj_pool_callback *cb;
};
#define PJ_POOL_SIZE (sizeof(struct pj_pool_t))
/**
* This constant denotes the exception number that will be thrown by default
* memory factory policy when memory allocation fails.
*/
PJ_DECL_DATA(int) PJ_NO_MEMORY_EXCEPTION;
/**
* Get #PJ_NO_MEMORY_EXCEPTION constant.
*/
PJ_DECL(int) pj_NO_MEMORY_EXCEPTION(void);
/*
* Declare all pool API as macro that calls the implementation
* function.
*/
#define pj_pool_create(fc,nm,init,inc,cb) \
pj_pool_create_imp(__FILE__, __LINE__, fc, nm, init, inc, cb)
#define pj_pool_release(pool) pj_pool_release_imp(pool)
#define pj_pool_safe_release(pool) pj_pool_safe_release_imp(pool)
#define pj_pool_secure_release(pool) pj_pool_secure_release_imp(pool)
#define pj_pool_getobjname(pool) pj_pool_getobjname_imp(pool)
#define pj_pool_reset(pool) pj_pool_reset_imp(pool)
#define pj_pool_get_capacity(pool) pj_pool_get_capacity_imp(pool)
#define pj_pool_get_used_size(pool) pj_pool_get_used_size_imp(pool)
#define pj_pool_alloc(pool,sz) \
pj_pool_alloc_imp(__FILE__, __LINE__, pool, sz)
#define pj_pool_calloc(pool,cnt,elem) \
pj_pool_calloc_imp(__FILE__, __LINE__, pool, cnt, elem)
#define pj_pool_zalloc(pool,sz) \
pj_pool_zalloc_imp(__FILE__, __LINE__, pool, sz)
/*
* Declare prototypes for pool implementation API.
*/
/* Create pool */
PJ_DECL(pj_pool_t*) pj_pool_create_imp(const char *file, int line,
void *factory,
const char *name,
pj_size_t initial_size,
pj_size_t increment_size,
pj_pool_callback *callback);
/* Release pool */
PJ_DECL(void) pj_pool_release_imp(pj_pool_t *pool);
/* Safe release pool */
PJ_DECL(void) pj_pool_safe_release_imp(pj_pool_t **pool);
/* Secure release pool */
PJ_DECL(void) pj_pool_secure_release_imp(pj_pool_t **pool);
/* Get pool name */
PJ_DECL(const char*) pj_pool_getobjname_imp(pj_pool_t *pool);
/* Reset pool */
PJ_DECL(void) pj_pool_reset_imp(pj_pool_t *pool);
/* Get capacity */
PJ_DECL(pj_size_t) pj_pool_get_capacity_imp(pj_pool_t *pool);
/* Get total used size */
PJ_DECL(pj_size_t) pj_pool_get_used_size_imp(pj_pool_t *pool);
/* Allocate memory from the pool */
PJ_DECL(void*) pj_pool_alloc_imp(const char *file, int line,
pj_pool_t *pool, pj_size_t sz);
/* Allocate memory from the pool and zero the memory */
PJ_DECL(void*) pj_pool_calloc_imp(const char *file, int line,
pj_pool_t *pool, unsigned cnt,
unsigned elemsz);
/* Allocate memory from the pool and zero the memory */
PJ_DECL(void*) pj_pool_zalloc_imp(const char *file, int line,
pj_pool_t *pool, pj_size_t sz);
#define PJ_POOL_ZALLOC_T(pool,type) \
((type*)pj_pool_zalloc(pool, sizeof(type)))
#define PJ_POOL_ALLOC_T(pool,type) \
((type*)pj_pool_alloc(pool, sizeof(type)))
#ifndef PJ_POOL_ALIGNMENT
# define PJ_POOL_ALIGNMENT 4
#endif
/**
* This structure declares pool factory interface.
*/
typedef struct pj_pool_factory_policy
{
/**
* Allocate memory block (for use by pool). This function is called
* by memory pool to allocate memory block.
*
* @param factory Pool factory.
* @param size The size of memory block to allocate.
*
* @return Memory block.
*/
void* (*block_alloc)(pj_pool_factory *factory, pj_size_t size);
/**
* Free memory block.
*
* @param factory Pool factory.
* @param mem Memory block previously allocated by block_alloc().
* @param size The size of memory block.
*/
void (*block_free)(pj_pool_factory *factory, void *mem, pj_size_t size);
/**
* Default callback to be called when memory allocation fails.
*/
pj_pool_callback *callback;
/**
* Option flags.
*/
unsigned flags;
} pj_pool_factory_policy;
struct pj_pool_factory
{
pj_pool_factory_policy policy;
int dummy;
};
struct pj_caching_pool
{
pj_pool_factory factory;
/* just to make it compilable */
unsigned used_count;
unsigned used_size;
unsigned peak_used_size;
};
/* just to make it compilable */
typedef struct pj_pool_block
{
int dummy;
} pj_pool_block;
#define pj_caching_pool_init( cp, pol, mac)
#define pj_caching_pool_destroy(cp)
#define pj_pool_factory_dump(pf, detail)
PJ_END_DECL
#endif /* __PJ_POOL_ALT_H__ */

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __POOL_STACK_H__
#define __POOL_STACK_H__
#include <pj/pool.h>
/**
* @defgroup PJ_POOL_BUFFER Stack/Buffer Based Memory Pool Allocator
* @ingroup PJ_POOL_GROUP
* @brief Stack/buffer based pool.
*
* This section describes an implementation of memory pool which uses
* memory allocated from the stack. Application creates this pool
* by specifying a buffer (which can be allocated from static memory or
* stack variable), and then use normal pool API to access/use the pool.
*
* If the buffer specified during pool creation is a buffer located in the
* stack, the pool will be invalidated (or implicitly destroyed) when the
* execution leaves the enclosing block containing the buffer. Note
* that application must make sure that any objects allocated from this
* pool (such as mutexes) have been destroyed before the pool gets
* invalidated.
*
* Sample usage:
*
* \code
#include <pjlib.h>
static void test()
{
char buffer[500];
pj_pool_t *pool;
void *p;
pool = pj_pool_create_on_buf("thepool", buffer, sizeof(buffer));
// Use the pool as usual
p = pj_pool_alloc(pool, ...);
...
// No need to release the pool
}
int main()
{
pj_init();
test();
return 0;
}
\endcode
*
* @{
*/
PJ_BEGIN_DECL
/**
* Create the pool using the specified buffer as the pool's memory.
* Subsequent allocations made from the pool will use the memory from
* this buffer.
*
* If the buffer specified in the parameter is a buffer located in the
* stack, the pool will be invalid (or implicitly destroyed) when the
* execution leaves the enclosing block containing the buffer. Note
* that application must make sure that any objects allocated from this
* pool (such as mutexes) have been destroyed before the pool gets
* invalidated.
*
* @param name Optional pool name.
* @param buf Buffer to be used by the pool.
* @param size The size of the buffer.
*
* @return The memory pool instance.
*/
PJ_DECL(pj_pool_t*) pj_pool_create_on_buf(const char *name,
void *buf,
pj_size_t size);
PJ_END_DECL
/**
* @}
*/
#endif /* __POOL_STACK_H__ */

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pj/string.h>
PJ_IDEF(pj_size_t) pj_pool_get_capacity( pj_pool_t *pool )
{
return pool->capacity;
}
PJ_IDEF(pj_size_t) pj_pool_get_used_size( pj_pool_t *pool )
{
pj_pool_block *b = pool->block_list.next;
pj_size_t used_size = sizeof(pj_pool_t);
while (b != &pool->block_list) {
used_size += (b->cur - b->buf) + sizeof(pj_pool_block);
b = b->next;
}
return used_size;
}
PJ_IDEF(void*) pj_pool_alloc_from_block( pj_pool_block *block, pj_size_t size )
{
/* The operation below is valid for size==0.
* When size==0, the function will return the pointer to the pool
* memory address, but no memory will be allocated.
*/
if (size & (PJ_POOL_ALIGNMENT-1)) {
size = (size + PJ_POOL_ALIGNMENT) & ~(PJ_POOL_ALIGNMENT-1);
}
if ((pj_size_t)(block->end - block->cur) >= size) {
void *ptr = block->cur;
block->cur += size;
return ptr;
}
return NULL;
}
PJ_IDEF(void*) pj_pool_alloc( pj_pool_t *pool, pj_size_t size)
{
void *ptr = pj_pool_alloc_from_block(pool->block_list.next, size);
if (!ptr)
ptr = pj_pool_allocate_find(pool, size);
return ptr;
}
PJ_IDEF(void*) pj_pool_calloc( pj_pool_t *pool, pj_size_t count, pj_size_t size)
{
void *buf = pj_pool_alloc( pool, size*count);
if (buf)
pj_bzero(buf, size * count);
return buf;
}
PJ_IDEF(const char *) pj_pool_getobjname( const pj_pool_t *pool )
{
return pool->obj_name;
}
PJ_IDEF(pj_pool_t*) pj_pool_create( pj_pool_factory *f,
const char *name,
pj_size_t initial_size,
pj_size_t increment_size,
pj_pool_callback *callback)
{
return (*f->create_pool)(f, name, initial_size, increment_size, callback);
}
PJ_IDEF(void) pj_pool_release( pj_pool_t *pool )
{
#if PJ_POOL_RELEASE_WIPE_DATA
pj_pool_block *b;
b = pool->block_list.next;
while (b != &pool->block_list) {
volatile unsigned char *p = b->buf;
while (p < b->end) *p++ = 0;
b = b->next;
}
#endif
if (pool->factory->release_pool)
(*pool->factory->release_pool)(pool->factory, pool);
}
PJ_IDEF(void) pj_pool_safe_release( pj_pool_t **ppool )
{
pj_pool_t *pool = *ppool;
*ppool = NULL;
if (pool)
pj_pool_release(pool);
}
PJ_IDEF(void) pj_pool_secure_release( pj_pool_t **ppool )
{
pj_pool_block *b;
pj_pool_t *pool = *ppool;
*ppool = NULL;
if (!pool)
return;
b = pool->block_list.next;
while (b != &pool->block_list) {
volatile unsigned char *p = b->buf;
while (p < b->end) *p++ = 0;
b = b->next;
}
pj_pool_release(pool);
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_RAND_H__
#define __PJ_RAND_H__
/**
* @file rand.h
* @brief Random Number Generator.
*/
#include <pj/config.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_RAND Random Number Generator
* @ingroup PJ_MISC
* @{
* This module contains functions for generating random numbers.
* This abstraction is needed not only because not all platforms have
* \a rand() and \a srand(), but also on some platforms \a rand()
* only has 16-bit randomness, which is not good enough.
*/
/**
* Put in seed to random number generator.
*
* @param seed Seed value.
*/
PJ_DECL(void) pj_srand(unsigned int seed);
/**
* Generate random integer with 32bit randomness.
*
* @return a random integer.
*/
PJ_DECL(int) pj_rand(void);
/** @} */
PJ_END_DECL
#endif /* __PJ_RAND_H__ */

View File

@@ -0,0 +1,215 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_RBTREE_H__
#define __PJ_RBTREE_H__
/**
* @file rbtree.h
* @brief Red/Black Tree
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_RBTREE Red/Black Balanced Tree
* @ingroup PJ_DS
* @brief
* Red/Black tree is the variant of balanced tree, where the search, insert,
* and delete operation is \b guaranteed to take at most \a O( lg(n) ).
* @{
*/
/**
* Color type for Red-Black tree.
*/
typedef enum pj_rbcolor_t
{
PJ_RBCOLOR_BLACK,
PJ_RBCOLOR_RED
} pj_rbcolor_t;
/**
* The type of the node of the R/B Tree.
*/
typedef struct pj_rbtree_node
{
/** Pointers to the node's parent. */
struct pj_rbtree_node *parent;
/** Pointers to the node's left sibling. */
struct pj_rbtree_node *left;
/** Pointers to the node's right sibling. */
struct pj_rbtree_node *right;
/** Key associated with the node. */
const void *key;
/** User data associated with the node. */
void *user_data;
/** The R/B Tree node color. */
pj_rbcolor_t color;
} pj_rbtree_node;
/**
* The type of function use to compare key value of tree node.
* @return
* 0 if the keys are equal
* <0 if key1 is lower than key2
* >0 if key1 is greater than key2.
*/
typedef int pj_rbtree_comp(const void *key1, const void *key2);
/**
* Declaration of a red-black tree. All elements in the tree must have UNIQUE
* key.
* A red black tree always maintains the balance of the tree, so that the
* tree height will not be greater than lg(N). Insert, search, and delete
* operation will take lg(N) on the worst case. But for insert and delete,
* there is additional time needed to maintain the balance of the tree.
*/
typedef struct pj_rbtree
{
pj_rbtree_node null_node; /**< Constant to indicate NULL node. */
pj_rbtree_node *null; /**< Constant to indicate NULL node. */
pj_rbtree_node *root; /**< Root tree node. */
unsigned size; /**< Number of elements in the tree. */
pj_rbtree_comp *comp; /**< Key comparison function. */
} pj_rbtree;
/**
* Guidance on how much memory required for each of the node.
*/
#define PJ_RBTREE_NODE_SIZE (sizeof(pj_rbtree_node))
/**
* Guidance on memory required for the tree.
*/
#define PJ_RBTREE_SIZE (sizeof(pj_rbtree))
/**
* Initialize the tree.
* @param tree the tree to be initialized.
* @param comp key comparison function to be used for this tree.
*/
PJ_DECL(void) pj_rbtree_init( pj_rbtree *tree, pj_rbtree_comp *comp);
/**
* Get the first element in the tree.
* The first element always has the least value for the key, according to
* the comparison function.
* @param tree the tree.
* @return the tree node, or NULL if the tree has no element.
*/
PJ_DECL(pj_rbtree_node*) pj_rbtree_first( pj_rbtree *tree );
/**
* Get the last element in the tree.
* The last element always has the greatest key value, according to the
* comparison function defined for the tree.
* @param tree the tree.
* @return the tree node, or NULL if the tree has no element.
*/
PJ_DECL(pj_rbtree_node*) pj_rbtree_last( pj_rbtree *tree );
/**
* Get the successive element for the specified node.
* The successive element is an element with greater key value.
* @param tree the tree.
* @param node the node.
* @return the successive node, or NULL if the node has no successor.
*/
PJ_DECL(pj_rbtree_node*) pj_rbtree_next( pj_rbtree *tree,
pj_rbtree_node *node );
/**
* The the previous node for the specified node.
* The previous node is an element with less key value.
* @param tree the tree.
* @param node the node.
* @return the previous node, or NULL if the node has no previous node.
*/
PJ_DECL(pj_rbtree_node*) pj_rbtree_prev( pj_rbtree *tree,
pj_rbtree_node *node );
/**
* Insert a new node.
* The node will be inserted at sorted location. The key of the node must
* be UNIQUE, i.e. it hasn't existed in the tree.
* @param tree the tree.
* @param node the node to be inserted.
* @return zero on success, or -1 if the key already exist.
*/
PJ_DECL(int) pj_rbtree_insert( pj_rbtree *tree,
pj_rbtree_node *node );
/**
* Find a node which has the specified key.
* @param tree the tree.
* @param key the key to search.
* @return the tree node with the specified key, or NULL if the key can not
* be found.
*/
PJ_DECL(pj_rbtree_node*) pj_rbtree_find( pj_rbtree *tree,
const void *key );
/**
* Erase a node from the tree.
* @param tree the tree.
* @param node the node to be erased.
* @return the tree node itself.
*/
PJ_DECL(pj_rbtree_node*) pj_rbtree_erase( pj_rbtree *tree,
pj_rbtree_node *node );
/**
* Get the maximum tree height from the specified node.
* @param tree the tree.
* @param node the node, or NULL to get the root of the tree.
* @return the maximum height, which should be at most lg(N)
*/
PJ_DECL(unsigned) pj_rbtree_max_height( pj_rbtree *tree,
pj_rbtree_node *node );
/**
* Get the minumum tree height from the specified node.
* @param tree the tree.
* @param node the node, or NULL to get the root of the tree.
* @return the height
*/
PJ_DECL(unsigned) pj_rbtree_min_height( pj_rbtree *tree,
pj_rbtree_node *node );
/**
* @}
*/
PJ_END_DECL
#endif /* __PJ_RBTREE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,429 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_SOCK_QOS_H__
#define __PJ_SOCK_QOS_H__
/**
* @file sock_qos.h
* @brief Socket QoS API
*/
#include <pj/sock.h>
PJ_BEGIN_DECL
/**
* @defgroup socket_qos Socket Quality of Service (QoS) API: TOS, DSCP, WMM, IEEE 802.1p
* @ingroup PJ_SOCK
* @{
\section intro QoS Technologies
QoS settings are available for both Layer 2 and 3 of TCP/IP protocols:
\subsection intro_ieee8021p Layer 2: IEEE 802.1p for Ethernet
IEEE 802.1p tagging will mark frames sent by a host for prioritized
delivery using a 3-bit Priority field in the virtual local area network
(VLAN) header of the Ethernet frame. The VLAN header is placed inside
the Ethernet header, between the Source Address field and either the
Length field (for an IEEE 802.3 frame) or the EtherType field (for an
Ethernet II frame).
\subsection intro_wmm Layer 2: WMM
At the Network Interface layer for IEEE 802.11 wireless, the Wi-Fi
Alliance certification for Wi-Fi Multimedia (WMM) defines four access
categories for prioritizing network traffic. These access categories
are (in order of highest to lowest priority) voice, video, best-effort,
and background. Host support for WMM prioritization requires that both
wireless network adapters and their drivers support WMM. Wireless
access points (APs) must have WMM enabled.
\subsection intro_dscp Layer 3: DSCP
At the Internet layer, you can use Differentiated Services/Diffserv and
set the value of the Differentiated Services Code Point (DSCP) in the
IP header. As defined in RFC 2474, the DSCP value is the high-order 6 bits
of the IP version 4 (IPv4) TOS field and the IP version 6 (IPv6) Traffic
Class field.
\subsection intro_other Layer 3: Other
Other mechanisms exist (such as RSVP, IntServ) but this will not be
implemented.
\section availability QoS Availability
\subsection linux Linux
DSCP is available via IP TOS option.
Ethernet 802.1p tagging is done by setting setsockopt(SO_PRIORITY) option
of the socket, then with the set_egress_map option of the vconfig utility
to convert this to set vlan-qos field of the packet.
WMM is not known to be available.
\subsection windows Windows and Windows Mobile
(It's a mess!)
DSCP is settable with setsockopt() on Windows 2000 or older, but Windows
would silently ignore this call on WinXP or later, unless administrator
modifies the registry. On Windows 2000, Windows XP, and Windows Server
2003, GQoS (Generic QoS) API is the standard API, but this API may not be
supported in the future. On Vista and Windows 7, the is a new QoS2 API,
also known as Quality Windows Audio-Video Experience (qWAVE).
IEEE 802.1p tagging is available via Traffic Control (TC) API, available
on Windows XP SP2, but this needs administrator access. For Vista and
later, it's in qWAVE.
WMM is available for mobile platforms on Windows Mobile 6 platform and
Windows Embedded CE 6, via setsockopt(IP_DSCP_TRAFFIC_TYPE). qWAVE
supports this as well.
\subsection symbian Symbian S60 3rd Ed
Both DSCP and WMM is supported via RSocket::SetOpt() with will set both
Layer 2 and Layer 3 QoS settings accordingly. Internally, PJLIB sets the
DSCP field of the socket, and based on certain DSCP values mapping,
Symbian will set the WMM tag accordingly.
\section api PJLIB's QoS API Abstraction
Based on the above, the following API is implemented.
Declare the following "standard" traffic types.
\code
typedef enum pj_qos_type
{
PJ_QOS_TYPE_BEST_EFFORT,
PJ_QOS_TYPE_BACKGROUND,
PJ_QOS_TYPE_VIDEO,
PJ_QOS_TYPE_VOICE,
PJ_QOS_TYPE_CONTROL,
PJ_QOS_TYPE_SIGNALLING
} pj_qos_type;
\endcode
The traffic classes above will determine how the Layer 2 and 3 QoS
settings will be used. The standard mapping between the classes above
to the corresponding Layer 2 and 3 settings are as follows:
\code
=================================================================
PJLIB Traffic Type IP DSCP WMM 802.1p
-----------------------------------------------------------------
BEST_EFFORT 0x00 BE (Bulk Effort) 0
BACKGROUND 0x08 BK (Bulk) 2
VIDEO 0x28 VI (Video) 5
VOICE 0x30 VO (Voice) 6
CONTROL 0x38 VO (Voice) 7
SIGNALLING 0x28 VI (Video) 5
=================================================================
\endcode
There are two sets of API provided to manipulate the QoS parameters.
\subsection portable_api Portable API
The first set of API is:
\code
// Set QoS parameters
PJ_DECL(pj_status_t) pj_sock_set_qos_type(pj_sock_t sock,
pj_qos_type val);
// Get QoS parameters
PJ_DECL(pj_status_t) pj_sock_get_qos_type(pj_sock_t sock,
pj_qos_type *p_val);
\endcode
The API will set the traffic type according to the DSCP class, for both
Layer 2 and Layer 3 QoS settings, where it's available. If any of the
layer QoS setting is not settable, the API will silently ignore it.
If both layers are not setable, the API will return error.
The API above is the recommended use of QoS, since it is the most
portable across all platforms.
\subsection detail_api Fine Grained Control API
The second set of API is intended for application that wants to fine
tune the QoS parameters.
The Layer 2 and 3 QoS parameters are stored in pj_qos_params structure:
\code
typedef enum pj_qos_flag
{
PJ_QOS_PARAM_HAS_DSCP = 1,
PJ_QOS_PARAM_HAS_SO_PRIO = 2,
PJ_QOS_PARAM_HAS_WMM = 4
} pj_qos_flag;
typedef enum pj_qos_wmm_prio
{
PJ_QOS_WMM_PRIO_BULK_EFFORT,
PJ_QOS_WMM_PRIO_BULK,
PJ_QOS_WMM_PRIO_VIDEO,
PJ_QOS_WMM_PRIO_VOICE
} pj_qos_wmm_prio;
typedef struct pj_qos_params
{
pj_uint8_t flags; // Determines which values to
// set, bitmask of pj_qos_flag
pj_uint8_t dscp_val; // The 6 bits DSCP value to set
pj_uint8_t so_prio; // SO_PRIORITY value
pj_qos_wmm_prio wmm_prio; // WMM priority value
} pj_qos_params;
\endcode
The second set of API with more fine-grained control over the parameters
are:
\code
// Retrieve QoS params for the specified traffic type
PJ_DECL(pj_status_t) pj_qos_get_params(pj_qos_type type,
pj_qos_params *p);
// Set QoS parameters to the socket
PJ_DECL(pj_status_t) pj_sock_set_qos_params(pj_sock_t sock,
const pj_qos_params *p);
// Get QoS parameters from the socket
PJ_DECL(pj_status_t) pj_sock_get_qos_params(pj_sock_t sock,
pj_qos_params *p);
\endcode
Important:
The pj_sock_set/get_qos_params() APIs are not portable, and it's probably
only going to be implemented on Linux. Application should always try to
use pj_sock_set_qos_type() instead.
*/
/**
* High level traffic classification.
*/
typedef enum pj_qos_type
{
PJ_QOS_TYPE_BEST_EFFORT, /**< Best effort traffic (default value).
Any QoS function calls with specifying
this value are effectively no-op */
PJ_QOS_TYPE_BACKGROUND, /**< Background traffic. */
PJ_QOS_TYPE_VIDEO, /**< Video traffic. */
PJ_QOS_TYPE_VOICE, /**< Voice traffic. */
PJ_QOS_TYPE_CONTROL, /**< Control traffic. */
PJ_QOS_TYPE_SIGNALLING /**< Signalling traffic. */
} pj_qos_type;
/**
* Bitmask flag to indicate which QoS layer setting is set in the
* \a flags field of the #pj_qos_params structure.
*/
typedef enum pj_qos_flag
{
PJ_QOS_PARAM_HAS_DSCP = 1, /**< DSCP field is set. */
PJ_QOS_PARAM_HAS_SO_PRIO = 2, /**< Socket SO_PRIORITY */
PJ_QOS_PARAM_HAS_WMM = 4 /**< WMM field is set. */
} pj_qos_flag;
/**
* Standard WMM priorities.
*/
typedef enum pj_qos_wmm_prio
{
PJ_QOS_WMM_PRIO_BULK_EFFORT, /**< Bulk effort priority */
PJ_QOS_WMM_PRIO_BULK, /**< Bulk priority. */
PJ_QOS_WMM_PRIO_VIDEO, /**< Video priority */
PJ_QOS_WMM_PRIO_VOICE /**< Voice priority */
} pj_qos_wmm_prio;
/**
* QoS parameters to be set or retrieved to/from the socket.
*/
typedef struct pj_qos_params
{
pj_uint8_t flags; /**< Determines which values to
set, bitmask of pj_qos_flag */
pj_uint8_t dscp_val; /**< The 6 bits DSCP value to set */
pj_uint8_t so_prio; /**< SO_PRIORITY value */
pj_qos_wmm_prio wmm_prio; /**< WMM priority value */
} pj_qos_params;
/**
* This is the high level and portable API to enable QoS on the specified
* socket, by setting the traffic type to the specified parameter.
*
* @param sock The socket.
* @param type Traffic type to be set.
*
* @return PJ_SUCCESS if at least Layer 2 or Layer 3 setting is
* successfully set. If both Layer 2 and Layer 3 settings
* can't be set, this function will return error.
*/
PJ_DECL(pj_status_t) pj_sock_set_qos_type(pj_sock_t sock,
pj_qos_type type);
/**
* This is the high level and portable API to get the traffic type that has
* been set on the socket. On occasions where the Layer 2 or Layer 3 settings
* were modified by using low level API, this function may return approximation
* of the closest QoS type that matches the settings.
*
* @param sock The socket.
* @param p_type Pointer to receive the traffic type of the socket.
*
* @return PJ_SUCCESS if traffic type for the socket can be obtained
* or approximated..
*/
PJ_DECL(pj_status_t) pj_sock_get_qos_type(pj_sock_t sock,
pj_qos_type *p_type);
/**
* This is a convenience function to apply QoS to the socket, and print error
* logging if the operations failed. Both QoS traffic type and the low level
* QoS parameters can be applied with this function.
*
* @param sock The socket handle.
* @param qos_type QoS traffic type. The QoS traffic type will be applied
* only if the value is not PJ_QOS_TYPE_BEST_EFFORT,
* @param qos_params Optional low-level QoS parameters. This will be
* applied only if this argument is not NULL and the
* flags inside the structure is non-zero. Upon return,
* the flags will indicate which parameters have been
* applied successfully.
* @param log_level This function will print to log at this level upon
* encountering errors.
* @param log_sender Optional sender name in the log.
* @param sock_name Optional name to help identify the socket in the log.
*
* @return PJ_SUCCESS if at least Layer 2 or Layer 3 setting is
* successfully set. If both Layer 2 and Layer 3 settings
* can't be set, this function will return error.
*
* @see pj_sock_apply_qos2()
*/
PJ_DECL(pj_status_t) pj_sock_apply_qos(pj_sock_t sock,
pj_qos_type qos_type,
pj_qos_params *qos_params,
unsigned log_level,
const char *log_sender,
const char *sock_name);
/**
* Variant of #pj_sock_apply_qos() where the \a qos_params parameter is
* const.
*
* @see pj_sock_apply_qos()
*/
PJ_DECL(pj_status_t) pj_sock_apply_qos2(pj_sock_t sock,
pj_qos_type qos_type,
const pj_qos_params *qos_params,
unsigned log_level,
const char *log_sender,
const char *sock_name);
/**
* Retrieve the standard mapping of QoS params for the specified traffic
* type.
*
* @param type The traffic type from which the QoS parameters
* are to be retrieved.
* @param p_param Pointer to receive the QoS parameters.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_qos_get_params(pj_qos_type type,
pj_qos_params *p_param);
/**
* Retrieve the traffic type that matches the specified QoS parameters.
* If no exact matching is found, this function will return an
* approximation of the closest matching traffic type for the specified
* QoS parameters.
*
* @param param Structure containing QoS parameters to map into
* "standard" traffic types.
* @param p_type Pointer to receive the traffic type.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_qos_get_type(const pj_qos_params *param,
pj_qos_type *p_type);
/**
* This is a low level API to set QoS parameters to the socket.
*
* @param sock The socket.
* @param param Structure containing QoS parameters to be applied
* to the socket. Upon return, the \a flags field
* of this structure will be set with bitmask value
* indicating which QoS settings have successfully
* been applied to the socket.
*
* @return PJ_SUCCESS if at least one field setting has been
* successfully set. If no setting can't be set,
* this function will return error.
*/
PJ_DECL(pj_status_t) pj_sock_set_qos_params(pj_sock_t sock,
pj_qos_params *param);
/**
* This is a low level API to get QoS parameters from the socket.
*
* @param sock The socket.
* @param p_param Pointer to receive the parameters. Upon returning
* successfully, the \a flags field of this structure
* will be initialized with the appropriate bitmask
* to indicate which fields have been successfully
* retrieved.
*
* @return PJ_SUCCESS on success or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_sock_get_qos_params(pj_sock_t sock,
pj_qos_params *p_param);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJ_SOCK_QOS_H__ */

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_SELECT_H__
#define __PJ_SELECT_H__
/**
* @file sock_select.h
* @brief Socket select().
*/
#include <pj/types.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_SOCK_SELECT Socket select() API.
* @ingroup PJ_IO
* @{
* This module provides portable abstraction for \a select() like API.
* The abstraction is needed so that it can utilize various event
* dispatching mechanisms that are available across platforms.
*
* The API is very similar to normal \a select() usage.
*
* \section pj_sock_select_examples_sec Examples
*
* For some examples on how to use the select API, please see:
*
* - Socket Select() test: \src{pjlib/src/pjlib-test/select.c}
*/
/**
* Portable structure declarations for pj_fd_set.
* The implementation of pj_sock_select() does not use this structure
* per-se, but instead it will use the native fd_set structure. However,
* we must make sure that the size of pj_fd_set_t can accomodate the
* native fd_set structure.
*/
typedef struct pj_fd_set_t
{
pj_sock_t data[PJ_IOQUEUE_MAX_HANDLES+ 4]; /**< Opaque buffer for fd_set */
} pj_fd_set_t;
/**
* Initialize the descriptor set pointed to by fdsetp to the null set.
*
* @param fdsetp The descriptor set.
*/
PJ_DECL(void) PJ_FD_ZERO(pj_fd_set_t *fdsetp);
/**
* This is an internal function, application shouldn't use this.
*
* Get the number of descriptors in the set. This is defined in sock_select.c
* This function will only return the number of sockets set from PJ_FD_SET
* operation. When the set is modified by other means (such as by select()),
* the count will not be reflected here.
*
* @param fdsetp The descriptor set.
*
* @return Number of descriptors in the set.
*/
PJ_DECL(pj_size_t) PJ_FD_COUNT(const pj_fd_set_t *fdsetp);
/**
* Add the file descriptor fd to the set pointed to by fdsetp.
* If the file descriptor fd is already in this set, there shall be no effect
* on the set, nor will an error be returned.
*
* @param fd The socket descriptor.
* @param fdsetp The descriptor set.
*/
PJ_DECL(void) PJ_FD_SET(pj_sock_t fd, pj_fd_set_t *fdsetp);
/**
* Remove the file descriptor fd from the set pointed to by fdsetp.
* If fd is not a member of this set, there shall be no effect on the set,
* nor will an error be returned.
*
* @param fd The socket descriptor.
* @param fdsetp The descriptor set.
*/
PJ_DECL(void) PJ_FD_CLR(pj_sock_t fd, pj_fd_set_t *fdsetp);
/**
* Evaluate to non-zero if the file descriptor fd is a member of the set
* pointed to by fdsetp, and shall evaluate to zero otherwise.
*
* @param fd The socket descriptor.
* @param fdsetp The descriptor set.
*
* @return Nonzero if fd is member of the descriptor set.
*/
PJ_DECL(pj_bool_t) PJ_FD_ISSET(pj_sock_t fd, const pj_fd_set_t *fdsetp);
/**
* This function wait for a number of file descriptors to change status.
* The behaviour is the same as select() function call which appear in
* standard BSD socket libraries.
*
* @param n On Unices, this specifies the highest-numbered
* descriptor in any of the three set, plus 1. On Windows,
* the value is ignored.
* @param readfds Optional pointer to a set of sockets to be checked for
* readability.
* @param writefds Optional pointer to a set of sockets to be checked for
* writability.
* @param exceptfds Optional pointer to a set of sockets to be checked for
* errors.
* @param timeout Maximum time for select to wait, or null for blocking
* operations.
*
* @return The total number of socket handles that are ready, or
* zero if the time limit expired, or -1 if an error occurred.
*/
PJ_DECL(int) pj_sock_select( int n,
pj_fd_set_t *readfds,
pj_fd_set_t *writefds,
pj_fd_set_t *exceptfds,
const pj_time_val *timeout);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJ_SELECT_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,963 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJ_STRING_H__
#define __PJ_STRING_H__
/**
* @file string.h
* @brief PJLIB String Operations.
*/
#include <pj/types.h>
#include <pj/compat/string.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_PSTR String Operations
* @ingroup PJ_DS
* @{
* This module provides string manipulation API.
*
* \section pj_pstr_not_null_sec PJLIB String is NOT Null Terminated!
*
* That is the first information that developers need to know. Instead
* of using normal C string, strings in PJLIB are represented as
* pj_str_t structure below:
*
* <pre>
* typedef struct pj_str_t
* {
* char *ptr;
* pj_ssize_t slen;
* } pj_str_t;
* </pre>
*
* There are some advantages of using this approach:
* - the string can point to arbitrary location in memory even
* if the string in that location is not null terminated. This is
* most usefull for text parsing, where the parsed text can just
* point to the original text in the input. If we use C string,
* then we will have to copy the text portion from the input
* to a string variable.
* - because the length of the string is known, string copy operation
* can be made more efficient.
*
* Most of APIs in PJLIB that expect or return string will represent
* the string as pj_str_t instead of normal C string.
*
* \section pj_pstr_examples_sec Examples
*
* For some examples, please see:
* - String test: \src{pjlib/src/pjlib-test/string.c}
*/
/**
* Check if a string is truncated and if yes, put a suffix of ".."
* to indicate the truncation.
* This macro is used to check the result of pj_ansi_snprintf().
*
* @param ret The return value of pj_ansi_snprintf().
* @param str The string.
* @param len The length of the string buffer.
*/
#define PJ_CHECK_TRUNC_STR(ret, str, len) \
if ((int)(ret) >= (int)(len) || (ret) < 0) pj_ansi_strxcpy((str) + (len) - 3, "..", 3)
/**
* Create string initializer from a normal C string.
*
* @param str Null terminated string to be stored.
*
* @return pj_str_t.
*/
PJ_IDECL(pj_str_t) pj_str(char *str);
/**
* Create constant string from normal C string.
*
* @param str The string to be initialized.
* @param s Null terminated string.
*
* @return pj_str_t.
*/
PJ_INLINE(const pj_str_t*) pj_cstr(pj_str_t *str, const char *s)
{
str->ptr = (char*)s;
str->slen = s ? (pj_ssize_t)strlen(s) : 0;
return str;
}
/**
* Set the pointer and length to the specified value.
*
* @param str the string.
* @param ptr pointer to set.
* @param length length to set.
*
* @return the string.
*/
PJ_INLINE(pj_str_t*) pj_strset( pj_str_t *str, char *ptr, pj_size_t length)
{
str->ptr = ptr;
str->slen = (pj_ssize_t)length;
return str;
}
/**
* Set the pointer and length of the string to the source string, which
* must be NULL terminated.
*
* @param str the string.
* @param src pointer to set.
*
* @return the string.
*/
PJ_INLINE(pj_str_t*) pj_strset2( pj_str_t *str, char *src)
{
str->ptr = src;
str->slen = src ? (pj_ssize_t)strlen(src) : 0;
return str;
}
/**
* Set the pointer and the length of the string.
*
* @param str The target string.
* @param begin The start of the string.
* @param end The end of the string.
*
* @return the target string.
*/
PJ_INLINE(pj_str_t*) pj_strset3( pj_str_t *str, char *begin, char *end )
{
str->ptr = begin;
str->slen = (pj_ssize_t)(end-begin);
return str;
}
/**
* Assign string.
*
* @param dst The target string.
* @param src The source string.
*
* @return the target string.
*/
PJ_IDECL(pj_str_t*) pj_strassign( pj_str_t *dst, pj_str_t *src );
/**
* Copy string contents.
*
* @param dst The target string.
* @param src The source string.
*
* @return the target string.
*/
PJ_IDECL(pj_str_t*) pj_strcpy(pj_str_t *dst, const pj_str_t *src);
/**
* Copy string contents.
*
* @param dst The target string.
* @param src The source string.
*
* @return the target string.
*/
PJ_IDECL(pj_str_t*) pj_strcpy2(pj_str_t *dst, const char *src);
/**
* Copy source string to destination up to the specified max length.
*
* @param dst The target string.
* @param src The source string.
* @param max Maximum characters to copy.
*
* @return the target string.
*/
PJ_IDECL(pj_str_t*) pj_strncpy(pj_str_t *dst, const pj_str_t *src,
pj_ssize_t max);
/**
* Copy source string to destination up to the specified max length,
* and NULL terminate the destination. If source string length is
* greater than or equal to max, then max-1 will be copied.
*
* @param dst The target string.
* @param src The source string.
* @param max Maximum characters to copy.
*
* @return the target string.
*/
PJ_IDECL(pj_str_t*) pj_strncpy_with_null(pj_str_t *dst, const pj_str_t *src,
pj_ssize_t max);
/**
* Duplicate string.
*
* @param pool The pool.
* @param dst The string result.
* @param src The string to duplicate.
*
* @return the string result.
*/
PJ_IDECL(pj_str_t*) pj_strdup(pj_pool_t *pool,
pj_str_t *dst,
const pj_str_t *src);
/**
* Duplicate string and NULL terminate the destination string.
*
* @param pool The pool.
* @param dst The string result.
* @param src The string to duplicate.
*
* @return The string result.
*/
PJ_IDECL(pj_str_t*) pj_strdup_with_null(pj_pool_t *pool,
pj_str_t *dst,
const pj_str_t *src);
/**
* Duplicate string.
*
* @param pool The pool.
* @param dst The string result.
* @param src The string to duplicate.
*
* @return the string result.
*/
PJ_IDECL(pj_str_t*) pj_strdup2(pj_pool_t *pool,
pj_str_t *dst,
const char *src);
/**
* Duplicate string and NULL terminate the destination string.
*
* @param pool The pool.
* @param dst The string result.
* @param src The string to duplicate.
*
* @return The string result.
*/
PJ_IDECL(pj_str_t*) pj_strdup2_with_null(pj_pool_t *pool,
pj_str_t *dst,
const char *src);
/**
* Duplicate string.
*
* @param pool The pool.
* @param src The string to duplicate.
*
* @return the string result.
*/
PJ_IDECL(pj_str_t) pj_strdup3(pj_pool_t *pool, const char *src);
/**
* Return the length of the string.
*
* @param str The string.
*
* @return the length of the string.
*/
PJ_INLINE(pj_size_t) pj_strlen( const pj_str_t *str )
{
return str->slen;
}
/**
* Return the pointer to the string data.
*
* @param str The string.
*
* @return the pointer to the string buffer.
*/
PJ_INLINE(const char*) pj_strbuf( const pj_str_t *str )
{
return str->ptr;
}
/**
* Compare strings.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
*
* @return
* - < 0 if str1 is less than str2
* - 0 if str1 is identical to str2
* - > 0 if str1 is greater than str2
*/
PJ_IDECL(int) pj_strcmp( const pj_str_t *str1, const pj_str_t *str2);
/**
* Compare strings.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
*
* @return
* - < 0 if str1 is less than str2
* - 0 if str1 is identical to str2
* - > 0 if str1 is greater than str2
*/
PJ_IDECL(int) pj_strcmp2( const pj_str_t *str1, const char *str2 );
/**
* Compare strings.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
* @param len The maximum number of characters to compare.
*
* @return
* - < 0 if str1 is less than str2
* - 0 if str1 is identical to str2
* - > 0 if str1 is greater than str2
*/
PJ_IDECL(int) pj_strncmp( const pj_str_t *str1, const pj_str_t *str2,
pj_size_t len);
/**
* Compare strings.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
* @param len The maximum number of characters to compare.
*
* @return
* - < 0 if str1 is less than str2
* - 0 if str1 is identical to str2
* - > 0 if str1 is greater than str2
*/
PJ_IDECL(int) pj_strncmp2( const pj_str_t *str1, const char *str2,
pj_size_t len);
/**
* Perform case-insensitive comparison to the strings.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
*
* @return
* - < 0 if str1 is less than str2
* - 0 if str1 is equal to str2
* - > 0 if str1 is greater than str2
*/
PJ_IDECL(int) pj_stricmp(const pj_str_t *str1, const pj_str_t *str2);
/**
* Perform lowercase comparison to the strings which consists of only
* alnum characters. More over, it will only return non-zero if both
* strings are not equal, not the usual negative or positive value.
*
* If non-alnum inputs are given, then the function may mistakenly
* treat two strings as equal.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
* @param len The length to compare.
*
* @return
* - 0 if str1 is equal to str2
* - (-1) if not equal.
*/
#if defined(PJ_HAS_STRICMP_ALNUM) && PJ_HAS_STRICMP_ALNUM!=0
PJ_IDECL(int) strnicmp_alnum(const char *str1, const char *str2,
int len);
#else
#define strnicmp_alnum pj_ansi_strnicmp
#endif
/**
* Perform lowercase comparison to the strings which consists of only
* alnum characters. More over, it will only return non-zero if both
* strings are not equal, not the usual negative or positive value.
*
* If non-alnum inputs are given, then the function may mistakenly
* treat two strings as equal.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
*
* @return
* - 0 if str1 is equal to str2
* - (-1) if not equal.
*/
#if defined(PJ_HAS_STRICMP_ALNUM) && PJ_HAS_STRICMP_ALNUM!=0
PJ_IDECL(int) pj_stricmp_alnum(const pj_str_t *str1, const pj_str_t *str2);
#else
#define pj_stricmp_alnum pj_stricmp
#endif
/**
* Perform case-insensitive comparison to the strings.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
*
* @return
* - < 0 if str1 is less than str2
* - 0 if str1 is identical to str2
* - > 0 if str1 is greater than str2
*/
PJ_IDECL(int) pj_stricmp2( const pj_str_t *str1, const char *str2);
/**
* Perform case-insensitive comparison to the strings.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
* @param len The maximum number of characters to compare.
*
* @return
* - < 0 if str1 is less than str2
* - 0 if str1 is identical to str2
* - > 0 if str1 is greater than str2
*/
PJ_IDECL(int) pj_strnicmp( const pj_str_t *str1, const pj_str_t *str2,
pj_size_t len);
/**
* Perform case-insensitive comparison to the strings.
*
* @param str1 The string to compare.
* @param str2 The string to compare.
* @param len The maximum number of characters to compare.
*
* @return
* - < 0 if str1 is less than str2
* - 0 if str1 is identical to str2
* - > 0 if str1 is greater than str2
*/
PJ_IDECL(int) pj_strnicmp2( const pj_str_t *str1, const char *str2,
pj_size_t len);
/**
* Concatenate strings.
*
* @param dst The destination string.
* @param src The source string.
*/
PJ_IDECL(void) pj_strcat(pj_str_t *dst, const pj_str_t *src);
/**
* Concatenate strings.
*
* @param dst The destination string.
* @param src The source string.
*/
PJ_IDECL(void) pj_strcat2(pj_str_t *dst, const char *src);
/**
* Finds a character in a string.
*
* @param str The string.
* @param chr The character to find.
*
* @return the pointer to first character found, or NULL.
*/
PJ_INLINE(char*) pj_strchr( const pj_str_t *str, int chr)
{
if (str->slen == 0)
return NULL;
return (char*) memchr((char*)str->ptr, chr, str->slen);
}
/**
* Find the first index of character, in a string, that does not belong to a
* set of characters.
*
* @param str The string.
* @param set_char The string containing the set of characters.
*
* @return the index of the first character in the str that doesn't belong to
* set_char. If str starts with a character not in set_char, return 0.
*/
PJ_DECL(pj_ssize_t) pj_strspn(const pj_str_t *str, const pj_str_t *set_char);
/**
* Find the first index of character, in a string, that does not belong to a
* set of characters.
*
* @param str The string.
* @param set_char The string containing the set of characters.
*
* @return the index of the first character in the str that doesn't belong to
* set_char. If str starts with a character not in set_char, return 0.
*/
PJ_DECL(pj_ssize_t) pj_strspn2(const pj_str_t *str, const char *set_char);
/**
* Find the first index of character, in a string, that belong to a set of
* characters.
*
* @param str The string.
* @param set_char The string containing the set of characters.
*
* @return the index of the first character in the str that belong to
* set_char. If no match is found, return the length of str.
*/
PJ_DECL(pj_ssize_t) pj_strcspn(const pj_str_t *str, const pj_str_t *set_char);
/**
* Find the first index of character, in a string, that belong to a set of
* characters.
*
* @param str The string.
* @param set_char The string containing the set of characters.
*
* @return the index of the first character in the str that belong to
* set_char. If no match is found, return the length of str.
*/
PJ_DECL(pj_ssize_t) pj_strcspn2(const pj_str_t *str, const char *set_char);
/**
* Find tokens from a string using the delimiter.
*
* @param str The string.
* @param delim The string containing the delimiter. It might contain
* multiple character treated as unique set. If same character
* was found on the set, it will be skipped.
* @param tok The string containing the token.
* @param start_idx The search will start from this index.
*
* @return the index of token from the str, or the length of the str
* if the token is not found.
*/
PJ_DECL(pj_ssize_t) pj_strtok(const pj_str_t *str, const pj_str_t *delim,
pj_str_t *tok, pj_size_t start_idx);
/**
* Find tokens from a string using the delimiter.
*
* @param str The string.
* @param delim The string containing the delimiter. It might contain
* multiple character treated as unique set. If same character
* was found on the set, it will be skipped.
* @param tok The string containing the token.
* @param start_idx The search will start from this index.
*
* @return the index of token from the str, or the length of the str
* if the token is not found.
*/
PJ_DECL(pj_ssize_t) pj_strtok2(const pj_str_t *str, const char *delim,
pj_str_t *tok, pj_size_t start_idx);
/**
* Find the occurence of a substring substr in string str.
*
* @param str The string to search.
* @param substr The string to search fo.
*
* @return the pointer to the position of substr in str, or NULL. Note
* that if str is not NULL terminated, the returned pointer
* is pointing to non-NULL terminated string.
*/
PJ_DECL(char*) pj_strstr(const pj_str_t *str, const pj_str_t *substr);
/**
* Performs substring lookup like pj_strstr() but ignores the case of
* both strings.
*
* @param str The string to search.
* @param substr The string to search fo.
*
* @return the pointer to the position of substr in str, or NULL. Note
* that if str is not NULL terminated, the returned pointer
* is pointing to non-NULL terminated string.
*/
PJ_DECL(char*) pj_stristr(const pj_str_t *str, const pj_str_t *substr);
/**
* Remove (trim) leading whitespaces from the string.
*
* @param str The string.
*
* @return the string.
*/
PJ_DECL(pj_str_t*) pj_strltrim( pj_str_t *str );
/**
* Remove (trim) the trailing whitespaces from the string.
*
* @param str The string.
*
* @return the string.
*/
PJ_DECL(pj_str_t*) pj_strrtrim( pj_str_t *str );
/**
* Remove (trim) leading and trailing whitespaces from the string.
*
* @param str The string.
*
* @return the string.
*/
PJ_IDECL(pj_str_t*) pj_strtrim( pj_str_t *str );
/**
* Initialize the buffer with some random string. Note that the
* generated string is not NULL terminated.
*
* @param str the string to store the result.
* @param length the length of the random string to generate.
*
* @return the string.
*/
PJ_DECL(char*) pj_create_random_string(char *str, pj_size_t length);
/**
* Convert string to signed integer. The conversion will stop as
* soon as non-digit character is found or all the characters have
* been processed.
*
* @param str the string.
*
* @return the integer.
*/
PJ_DECL(long) pj_strtol(const pj_str_t *str);
/**
* Convert string to signed long integer. The conversion will stop as
* soon as non-digit character is found or all the characters have
* been processed.
*
* @param str the string.
* @param value Pointer to a long to receive the value.
*
* @return PJ_SUCCESS if successful. Otherwise:
* PJ_ETOOSMALL if the value was an impossibly long negative number.
* In this case *value will be set to LONG_MIN.
* \n
* PJ_ETOOBIG if the value was an impossibly long positive number.
* In this case, *value will be set to LONG_MAX.
* \n
* PJ_EINVAL if the input string was NULL, the value pointer was NULL
* or the input string could not be parsed at all such as starting with
* a character other than a '+', '-' or not in the '0' - '9' range.
* In this case, *value will be left untouched.
*/
PJ_DECL(pj_status_t) pj_strtol2(const pj_str_t *str, long *value);
/**
* Convert string to unsigned integer. The conversion will stop as
* soon as non-digit character is found or all the characters have
* been processed.
*
* @param str the string.
*
* @return the unsigned integer.
*/
PJ_DECL(unsigned long) pj_strtoul(const pj_str_t *str);
/**
* Convert strings to an unsigned long-integer value.
* This function stops reading the string input either when the number
* of characters has exceeded the length of the input or it has read
* the first character it cannot recognize as part of a number, that is
* a character greater than or equal to base.
*
* @param str The input string.
* @param endptr Optional pointer to receive the remainder/unparsed
* portion of the input.
* @param base Number base to use.
*
* @return the unsigned integer number.
*/
PJ_DECL(unsigned long) pj_strtoul2(const pj_str_t *str, pj_str_t *endptr,
unsigned base);
/**
* Convert string to unsigned long integer. The conversion will stop as
* soon as non-digit character is found or all the characters have
* been processed.
*
* @param str The input string.
* @param value Pointer to an unsigned long to receive the value.
* @param base Number base to use.
*
* @return PJ_SUCCESS if successful. Otherwise:
* PJ_ETOOBIG if the value was an impossibly long positive number.
* In this case, *value will be set to ULONG_MAX.
* \n
* PJ_EINVAL if the input string was NULL, the value pointer was NULL
* or the input string could not be parsed at all such as starting
* with a character outside the base character range. In this case,
* *value will be left untouched.
*/
PJ_DECL(pj_status_t) pj_strtoul3(const pj_str_t *str, unsigned long *value,
unsigned base);
/**
* Convert string to generic unsigned integer. The conversion will stop as
* soon as non-digit character is found or all the characters have
* been processed.
*
* @param str The input string.
* @param value Pointer to an unsigned integer to receive the value.
* The value will be a 64 bit unsigned integer if the system
* supports it, otherwise a 32 bit unsigned integer.
* @param base Number base to use.
*
* @return PJ_SUCCESS if successful. Otherwise:
* PJ_ETOOBIG if the value was an impossibly long positive number.
* In this case, *value will be set to ULLONG_MAX (for 64 bit) or
* ULONG_MAX (for 32 bit).
* \n
* PJ_EINVAL if the input string was NULL, the value pointer was NULL
* or the input string could not be parsed at all such as starting
* with a character outside the base character range. In this case,
* *value will be left untouched.
*/
PJ_DECL(pj_status_t) pj_strtoul4(const pj_str_t *str, pj_uint_t *value,
unsigned base);
/**
* Convert string to float.
*
* @param str the string.
*
* @return the value.
*/
PJ_DECL(float) pj_strtof(const pj_str_t *str);
/**
* Utility to convert unsigned integer to string. Note that the
* string will be NULL terminated.
*
* @param val the unsigned integer value.
* @param buf the buffer
*
* @return the number of characters written
*/
PJ_DECL(int) pj_utoa(unsigned long val, char *buf);
/**
* Utility to convert generic unsigned integer to string. Note that the
* string will be NULL terminated.
*
* This function will take 64 bit unsigned integer if the system has one,
* otherwise it takes 32 bit unsigned integer.
*
* @param val the unsigned integer value.
* @param buf the buffer
*
* @return the number of characters written
*/
PJ_DECL(int) pj_utoa2(pj_uint_t val, char *buf);
/**
* Convert unsigned integer to string with minimum digits. Note that the
* string will be NULL terminated.
*
* @param val The unsigned integer value.
* @param buf The buffer.
* @param min_dig Minimum digits to be printed, or zero to specify no
* minimum digit.
* @param pad The padding character to be put in front of the string
* when the digits is less than minimum.
*
* @return the number of characters written.
*/
PJ_DECL(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad);
/**
* Convert generic unsigned integer to string with minimum digits. Note that
* the string will be NULL terminated.
*
* This function will take 64 bit unsigned integer if the system has one,
* otherwise it takes 32 bit unsigned integer.
*
* @param val The unsigned integer value.
* @param buf The buffer.
* @param min_dig Minimum digits to be printed, or zero to specify no
* minimum digit.
* @param pad The padding character to be put in front of the string
* when the digits is less than minimum.
*
* @return the number of characters written.
*/
PJ_DECL(int) pj_utoa_pad2( pj_uint_t val, char *buf, int min_dig, int pad);
/**
* Fill the memory location with zero.
*
* @param dst The destination buffer.
* @param size The number of bytes.
*/
PJ_INLINE(void) pj_bzero(void *dst, pj_size_t size)
{
#if defined(PJ_HAS_BZERO) && PJ_HAS_BZERO!=0
bzero(dst, size);
#else
memset(dst, 0, size);
#endif
}
/**
* Fill the memory location with value.
*
* @param dst The destination buffer.
* @param c Character to set.
* @param size The number of characters.
*
* @return the value of dst.
*/
PJ_INLINE(void*) pj_memset(void *dst, int c, pj_size_t size)
{
return memset(dst, c, size);
}
/**
* Copy buffer.
*
* @param dst The destination buffer.
* @param src The source buffer.
* @param size The size to copy.
*
* @return the destination buffer.
*/
PJ_INLINE(void*) pj_memcpy(void *dst, const void *src, pj_size_t size)
{
return memcpy(dst, src, size);
}
/**
* Move memory.
*
* @param dst The destination buffer.
* @param src The source buffer.
* @param size The size to copy.
*
* @return the destination buffer.
*/
PJ_INLINE(void*) pj_memmove(void *dst, const void *src, pj_size_t size)
{
return memmove(dst, src, size);
}
/**
* Compare buffers.
*
* @param buf1 The first buffer.
* @param buf2 The second buffer.
* @param size The size to compare.
*
* @return negative, zero, or positive value.
*/
PJ_INLINE(int) pj_memcmp(const void *buf1, const void *buf2, pj_size_t size)
{
return memcmp(buf1, buf2, size);
}
/**
* Find character in the buffer.
*
* @param buf The buffer.
* @param c The character to find.
* @param size The size to check.
*
* @return the pointer to location where the character is found, or NULL if
* not found.
*/
PJ_INLINE(void*) pj_memchr(const void *buf, int c, pj_size_t size)
{
return (void*)memchr((void*)buf, c, size);
}
/**
* Copy the string, or as much of it as fits, into the dest buffer.
* Regardless of whether all characters were copied, the destination
* buffer will be null terminated, unless dst_size is zero which in
* this case nothing will be written to dst and the function will
* return -PJ_ETOOBIG.
*
* @param dst The destination string.
* @param src The source string.
* @param dst_size The full size of the destination string buffer.
*
* @return The number of characters copied (not including the trailing NUL) or
* -PJ_ETOOBIG if the destination buffer wasn't big enough,
* -PJ_EINVAL if the dst or src is NULL.
*/
PJ_DECL(int) pj_ansi_strxcpy(char *dst, const char *src, pj_size_t dst_size);
/**
* Same as pj_ansi_strxcpy() but takes pj_str_t as the source.
* If src contains null character, copying will stop at the first null
* character in src.
*
* @param dst The destination string.
* @param src The source string.
* @param dst_size The full size of the destination string buffer.
*
* @return The number of characters copied (not including the trailing NUL) or
* -PJ_ETOOBIG if the destination buffer wasn't big enough,
* -PJ_EINVAL if the dst or src is NULL.
*/
PJ_DECL(int) pj_ansi_strxcpy2(char *dst, const pj_str_t *src,
pj_size_t dst_size);
/**
* Concatenate src, or as much of it as fits, into the dest buffer.
* Regardless of whether all characters were copied, the destination
* buffer will be null terminated, unless dst_size is zero which in
* this case nothing will be written to dst and the function will
* return -PJ_ETOOBIG.
*
* @param dst The destination string.
* @param src The source string.
* @param dst_size The full size of the destination string buffer.
*
* @return Final length of dst string (not including the trailing NUL) or
* -PJ_ETOOBIG if the destination buffer wasn't big enough,
* -PJ_EINVAL if the dst or src is NULL.
*/
PJ_DECL(int) pj_ansi_strxcat(char *dst, const char *src, pj_size_t dst_size);
/**
* @}
*/
#if PJ_FUNCTIONS_ARE_INLINED
# include <pj/string_i.h>
#endif
PJ_END_DECL
#endif /* __PJ_STRING_H__ */

View File

@@ -0,0 +1,406 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pj/assert.h>
#include <pj/pool.h>
PJ_IDEF(pj_str_t) pj_str(char *str)
{
pj_str_t dst;
dst.ptr = str;
dst.slen = str ? pj_ansi_strlen(str) : 0;
return dst;
}
PJ_IDEF(pj_str_t*) pj_strdup(pj_pool_t *pool,
pj_str_t *dst,
const pj_str_t *src)
{
pj_assert(src->slen >= 0);
/* Without this, destination will be corrupted */
if (dst == src)
return dst;
if (src->slen > 0) {
dst->ptr = (char*)pj_pool_alloc(pool, src->slen);
pj_memcpy(dst->ptr, src->ptr, src->slen);
}
dst->slen = (src->slen < 0)? 0: src->slen;
return dst;
}
PJ_IDEF(pj_str_t*) pj_strdup_with_null( pj_pool_t *pool,
pj_str_t *dst,
const pj_str_t *src)
{
pj_ssize_t src_slen = src->slen;
pj_assert(src->slen >= 0);
/* Check if the source's length is invalid */
if (src_slen < 0)
src_slen = 0;
dst->ptr = (char*)pj_pool_alloc(pool, src_slen+1);
if (src_slen) {
pj_memcpy(dst->ptr, src->ptr, src_slen);
}
dst->slen = src_slen;
dst->ptr[dst->slen] = '\0';
return dst;
}
PJ_IDEF(pj_str_t*) pj_strdup2(pj_pool_t *pool,
pj_str_t *dst,
const char *src)
{
dst->slen = src ? pj_ansi_strlen(src) : 0;
if (dst->slen) {
dst->ptr = (char*)pj_pool_alloc(pool, dst->slen);
pj_memcpy(dst->ptr, src, dst->slen);
} else {
dst->ptr = NULL;
}
return dst;
}
PJ_IDEF(pj_str_t*) pj_strdup2_with_null( pj_pool_t *pool,
pj_str_t *dst,
const char *src)
{
dst->slen = src ? pj_ansi_strlen(src) : 0;
dst->ptr = (char*)pj_pool_alloc(pool, dst->slen+1);
if (dst->slen) {
pj_memcpy(dst->ptr, src, dst->slen);
}
dst->ptr[dst->slen] = '\0';
return dst;
}
PJ_IDEF(pj_str_t) pj_strdup3(pj_pool_t *pool, const char *src)
{
pj_str_t temp;
pj_strdup2(pool, &temp, src);
return temp;
}
PJ_IDEF(pj_str_t*) pj_strassign( pj_str_t *dst, pj_str_t *src )
{
dst->ptr = src->ptr;
dst->slen = src->slen;
return dst;
}
PJ_IDEF(pj_str_t*) pj_strcpy(pj_str_t *dst, const pj_str_t *src)
{
pj_assert(src->slen >= 0);
dst->slen = (src->slen < 0)? 0: src->slen;
if (src->slen > 0)
pj_memcpy(dst->ptr, src->ptr, src->slen);
return dst;
}
PJ_IDEF(pj_str_t*) pj_strcpy2(pj_str_t *dst, const char *src)
{
dst->slen = src ? pj_ansi_strlen(src) : 0;
if (dst->slen > 0)
pj_memcpy(dst->ptr, src, dst->slen);
return dst;
}
PJ_IDEF(pj_str_t*) pj_strncpy( pj_str_t *dst, const pj_str_t *src,
pj_ssize_t max)
{
pj_assert(src->slen >= 0);
pj_assert(max >= 0);
if (max > src->slen) max = src->slen;
if (max > 0)
pj_memcpy(dst->ptr, src->ptr, max);
dst->slen = (max < 0)? 0: max;
return dst;
}
PJ_IDEF(pj_str_t*) pj_strncpy_with_null( pj_str_t *dst, const pj_str_t *src,
pj_ssize_t max)
{
pj_assert(src->slen >= 0);
pj_assert(max > 0);
if (max <= src->slen)
max = (max > 0)? max-1: 0;
else
max = (src->slen < 0)? 0: src->slen;
if (max > 0)
pj_memcpy(dst->ptr, src->ptr, max);
dst->ptr[max] = '\0';
dst->slen = max;
return dst;
}
PJ_IDEF(int) pj_strcmp( const pj_str_t *str1, const pj_str_t *str2)
{
pj_assert(str1->slen >= 0);
pj_assert(str2->slen >= 0);
if (str1->slen <= 0) {
return str2->slen<=0 ? 0 : -1;
} else if (str2->slen <= 0) {
return 1;
} else {
pj_size_t min = (str1->slen < str2->slen)? str1->slen : str2->slen;
int res = pj_memcmp(str1->ptr, str2->ptr, min);
if (res == 0) {
return (str1->slen < str2->slen) ? -1 :
(str1->slen == str2->slen ? 0 : 1);
} else {
return res;
}
}
}
PJ_IDEF(int) pj_strncmp( const pj_str_t *str1, const pj_str_t *str2,
pj_size_t len)
{
pj_str_t copy1, copy2;
pj_assert(str1->slen >= 0);
pj_assert(str2->slen >= 0);
if (len < (unsigned)str1->slen && str1->slen > 0) {
copy1.ptr = str1->ptr;
copy1.slen = len;
str1 = &copy1;
}
if (len < (unsigned)str2->slen && str2->slen > 0) {
copy2.ptr = str2->ptr;
copy2.slen = len;
str2 = &copy2;
}
return pj_strcmp(str1, str2);
}
PJ_IDEF(int) pj_strncmp2( const pj_str_t *str1, const char *str2,
pj_size_t len)
{
pj_str_t copy2;
if (str2) {
copy2.ptr = (char*)str2;
copy2.slen = pj_ansi_strlen(str2);
} else {
copy2.slen = 0;
}
return pj_strncmp(str1, &copy2, len);
}
PJ_IDEF(int) pj_strcmp2( const pj_str_t *str1, const char *str2 )
{
pj_str_t copy2;
if (str2) {
copy2.ptr = (char*)str2;
copy2.slen = pj_ansi_strlen(str2);
} else {
copy2.ptr = NULL;
copy2.slen = 0;
}
return pj_strcmp(str1, &copy2);
}
PJ_IDEF(int) pj_stricmp( const pj_str_t *str1, const pj_str_t *str2)
{
pj_assert(str1->slen >= 0);
pj_assert(str2->slen >= 0);
if (str1->slen <= 0) {
return str2->slen<=0 ? 0 : -1;
} else if (str2->slen <= 0) {
return 1;
} else {
pj_size_t min = (str1->slen < str2->slen)? str1->slen : str2->slen;
int res = pj_ansi_strnicmp(str1->ptr, str2->ptr, min);
if (res == 0) {
return (str1->slen < str2->slen) ? -1 :
(str1->slen == str2->slen ? 0 : 1);
} else {
return res;
}
}
}
#if defined(PJ_HAS_STRICMP_ALNUM) && PJ_HAS_STRICMP_ALNUM!=0
PJ_IDEF(int) strnicmp_alnum( const char *str1, const char *str2,
int len)
{
if (len==0)
return 0;
else {
register const pj_uint32_t *p1 = (pj_uint32_t*)str1,
*p2 = (pj_uint32_t*)str2;
while (len > 3 && (*p1 & 0x5F5F5F5F)==(*p2 & 0x5F5F5F5F))
++p1, ++p2, len-=4;
if (len > 3)
return -1;
#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
else if (len==3)
return ((*p1 & 0x005F5F5F)==(*p2 & 0x005F5F5F)) ? 0 : -1;
else if (len==2)
return ((*p1 & 0x00005F5F)==(*p2 & 0x00005F5F)) ? 0 : -1;
else if (len==1)
return ((*p1 & 0x0000005F)==(*p2 & 0x0000005F)) ? 0 : -1;
#else
else if (len==3)
return ((*p1 & 0x5F5F5F00)==(*p2 & 0x5F5F5F00)) ? 0 : -1;
else if (len==2)
return ((*p1 & 0x5F5F0000)==(*p2 & 0x5F5F0000)) ? 0 : -1;
else if (len==1)
return ((*p1 & 0x5F000000)==(*p2 & 0x5F000000)) ? 0 : -1;
#endif
else
return 0;
}
}
PJ_IDEF(int) pj_stricmp_alnum(const pj_str_t *str1, const pj_str_t *str2)
{
register int len = str1->slen;
if (len != str2->slen) {
return (len < str2->slen) ? -1 : 1;
} else if (len == 0) {
return 0;
} else {
register const pj_uint32_t *p1 = (pj_uint32_t*)str1->ptr,
*p2 = (pj_uint32_t*)str2->ptr;
while (len > 3 && (*p1 & 0x5F5F5F5F)==(*p2 & 0x5F5F5F5F))
++p1, ++p2, len-=4;
if (len > 3)
return -1;
#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
else if (len==3)
return ((*p1 & 0x005F5F5F)==(*p2 & 0x005F5F5F)) ? 0 : -1;
else if (len==2)
return ((*p1 & 0x00005F5F)==(*p2 & 0x00005F5F)) ? 0 : -1;
else if (len==1)
return ((*p1 & 0x0000005F)==(*p2 & 0x0000005F)) ? 0 : -1;
#else
else if (len==3)
return ((*p1 & 0x5F5F5F00)==(*p2 & 0x5F5F5F00)) ? 0 : -1;
else if (len==2)
return ((*p1 & 0x5F5F0000)==(*p2 & 0x5F5F0000)) ? 0 : -1;
else if (len==1)
return ((*p1 & 0x5F000000)==(*p2 & 0x5F000000)) ? 0 : -1;
#endif
else
return 0;
}
}
#endif /* PJ_HAS_STRICMP_ALNUM */
PJ_IDEF(int) pj_stricmp2( const pj_str_t *str1, const char *str2)
{
pj_str_t copy2;
if (str2) {
copy2.ptr = (char*)str2;
copy2.slen = pj_ansi_strlen(str2);
} else {
copy2.ptr = NULL;
copy2.slen = 0;
}
return pj_stricmp(str1, &copy2);
}
PJ_IDEF(int) pj_strnicmp( const pj_str_t *str1, const pj_str_t *str2,
pj_size_t len)
{
pj_str_t copy1, copy2;
if (len < (unsigned)str1->slen && str1->slen > 0) {
copy1.ptr = str1->ptr;
copy1.slen = len;
str1 = &copy1;
}
if (len < (unsigned)str2->slen && str2->slen > 0) {
copy2.ptr = str2->ptr;
copy2.slen = len;
str2 = &copy2;
}
return pj_stricmp(str1, str2);
}
PJ_IDEF(int) pj_strnicmp2( const pj_str_t *str1, const char *str2,
pj_size_t len)
{
pj_str_t copy2;
if (str2) {
copy2.ptr = (char*)str2;
copy2.slen = pj_ansi_strlen(str2);
} else {
copy2.slen = 0;
}
return pj_strnicmp(str1, &copy2, len);
}
PJ_IDEF(void) pj_strcat(pj_str_t *dst, const pj_str_t *src)
{
pj_assert(src->slen >= 0);
pj_assert(dst->slen >= 0);
if (src->slen > 0 && dst->slen >= 0) {
pj_memcpy(dst->ptr + dst->slen, src->ptr, src->slen);
dst->slen += src->slen;
}
}
PJ_IDEF(void) pj_strcat2(pj_str_t *dst, const char *str)
{
pj_size_t len = str? pj_ansi_strlen(str) : 0;
pj_assert(dst->slen >= 0);
if (len && dst->slen >= 0) {
pj_memcpy(dst->ptr + dst->slen, str, len);
dst->slen += len;
}
}
PJ_IDEF(pj_str_t*) pj_strtrim( pj_str_t *str )
{
pj_strltrim(str);
pj_strrtrim(str);
return str;
}

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