⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iaxclient_lib.c

📁 ppciaxclient softphone
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * iaxclient: a cross-platform IAX softphone library
 *
 * Copyrights:
 * Copyright (C) 2003 HorizonLive.com, (c) 2004, Horizon Wimba, Inc.
 *
 * Contributors:
 * Steve Kann <stevek@stevek.com>
 * Michael Van Donselaar <mvand@vandonselaar.org> 
 * Shawn Lawrence <shawn.lawrence@terracecomm.com>
 *
 *
 * This program is free software, distributed under the terms of
 * the GNU Lesser (Library) General Public License
 */
#include "iaxclient_lib.h"
#include "jitterbuf.h"

#if defined(__STDC__) || defined(_MSC_VER)
#include <stdarg.h>
#define LIBVER "CVS-2005/08/10-13:00"
#define vsnprintf _vsnprintf
#else
#include <varargs.h>
#endif

#define IAXC_ERROR  IAXC_TEXT_TYPE_ERROR
#define IAXC_STATUS IAXC_TEXT_TYPE_STATUS
#define IAXC_NOTICE IAXC_TEXT_TYPE_NOTICE

#define DEFAULT_CALLERID_NAME    "Not Available"
#define DEFAULT_CALLERID_NUMBER  "7005551212"
#ifdef _DEBUG
struct iax_session *iepsession;
#endif
struct iaxc_registration {
    struct iax_session *session;
    struct timeval last;
    char host[256];
    char user[256];
    char pass[256];
    long refresh;
    int id;
    struct iaxc_registration *next;
};

struct tiaxc_nattrv {
	struct iax_session *session;
	struct timeval last;
	char host[256];
	char callerid[256];
	long refresh;
	int id;
	struct tiaxc_nattrv *next;
};


static int next_registration_id = 0;
static struct iaxc_registration *registrations = NULL;
// Tili Edit
static int next_nattrv_id = 0;
static struct tiaxc_nattrv *nattrvs = NULL;

// Tili Edit End

struct iaxc_audio_driver audio;

static int iAudioType;

int audio_format_capability;
int audio_format_preferred;

void * post_event_handle = NULL;
int post_event_id = 0;

static int minimum_outgoing_framesize = 160; /* 20ms */

static MUTEX iaxc_lock;
 
int netfd;
int port;
int c, i;

int iaxc_audio_output_mode = 0; // Normal

static int selected_call; // XXX to be protected by mutex?
static struct iaxc_call* calls;
static int nCalls;	// number of calls for this library session

struct timeval lastouttm;

static void iaxc_service_network();
static int service_audio();

/* external global networking replacements */
static iaxc_sendto_t   iaxc_sendto = sendto;
static iaxc_recvfrom_t iaxc_recvfrom = recvfrom;


static THREAD procThread;
#ifdef WIN32
static THREADID procThreadID;
#endif

/* QuitFlag: 0: Running 1: Should Quit, -1: Not Running */
static int procThreadQuitFlag = -1;

static iaxc_event_callback_t iaxc_event_callback = NULL;

// Internal queue of events, waiting to be posted once the library
// lock is released.
static iaxc_event *event_queue = NULL;

// Record whether lock is held, so we know whether to send events now
// or queue them until the lock is released.
static int iaxc_locked = 0;

// Lock the library
static void get_iaxc_lock() {
    MUTEXLOCK(&iaxc_lock);
    iaxc_locked = 1;
}

// Unlock the library and post any events that were queued in the meantime
static void put_iaxc_lock() {
    iaxc_event *prev, *event = event_queue;
    event_queue = NULL;
    iaxc_locked = 0;
    MUTEXUNLOCK(&iaxc_lock);
    while (event) {
	iaxc_post_event(*event);
	prev = event;
	event = event->next;
	free(prev);
    }
}


EXPORT void iaxc_set_silence_threshold(double thr) {
    iaxc_silence_threshold = thr;
    iaxc_set_speex_filters();
}

EXPORT void iaxc_set_audio_output(int mode) {
    iaxc_audio_output_mode = mode;
}


EXPORT int iaxc_get_filters(void) {
      return iaxc_filters;
}

EXPORT void iaxc_set_filters(int filters) {
      iaxc_filters = filters;
      iaxc_set_speex_filters();
}


long iaxc_usecdiff( struct timeval *timeA, struct timeval *timeB ){
      long secs = timeA->tv_sec - timeB->tv_sec;
      long usecs = secs * 1000000;
      usecs += (timeA->tv_usec - timeB->tv_usec);
      return usecs;
}

EXPORT void iaxc_set_event_callback(iaxc_event_callback_t func) {
    iaxc_event_callback = func;
}

EXPORT int iaxc_set_event_callpost(void *handle, int id) {
    post_event_handle = handle;
    post_event_id = id;
    iaxc_event_callback = post_event_callback; 
    return 0;
}

EXPORT void iaxc_free_event(iaxc_event *e) {
    free(e);
}

EXPORT struct iaxc_ev_levels *iaxc_get_event_levels(iaxc_event *e) {
    return &e->ev.levels;
}
EXPORT struct iaxc_ev_text *iaxc_get_event_text(iaxc_event *e) {
    return &e->ev.text;
}
EXPORT struct iaxc_ev_call_state *iaxc_get_event_state(iaxc_event *e) {
    return &e->ev.call;
}


// Messaging functions
static void default_message_callback(char *message) {
  fprintf(stderr, "IAXCLIENT: ");
  fprintf(stderr, message);
  fprintf(stderr, "\n");
}

// Post Events back to clients
void iaxc_post_event(iaxc_event e) {

    if(e.type == 0) {
	iaxc_usermsg(IAXC_ERROR, "Error: something posted to us an invalid event");
	return;
    }
	
    // If the library is locked then just queue the event to be posted
    // once the lock is released.
    if (iaxc_locked)
    {
	iaxc_event **tail = &event_queue;
	e.next = NULL;
	while (*tail)
	    tail = &((*tail)->next);
	*tail = malloc(sizeof(iaxc_event));
	memcpy(*tail, &e, sizeof(iaxc_event));
	return;
    }
    // Library is not locked, so process event now.
    if(iaxc_event_callback)
    {
	int rv;
	rv = iaxc_event_callback(e);
	if(rv < 0) 
	  default_message_callback("IAXCLIENT: BIG PROBLEM, event callback returned failure!");
	// > 0 means processed
	if(rv > 0) return;

	// else, fall through to "defaults"
    }

    switch(e.type)
    {
	case IAXC_EVENT_TEXT:
	    default_message_callback(e.ev.text.message);
	// others we just ignore too
	return;
    }
}


void iaxc_usermsg(int type, const char *fmt, ...)
{
    va_list args;
    iaxc_event e;

    e.type=IAXC_EVENT_TEXT;
    e.ev.text.type=type;

    va_start(args, fmt);
    vsnprintf(e.ev.text.message, IAXC_EVENT_BUFSIZ, fmt, args);
    va_end(args);

    iaxc_post_event(e);
}


void iaxc_do_levels_callback(float input, float output)
{
    iaxc_event e;
    e.type = IAXC_EVENT_LEVELS;
    e.ev.levels.input = input;
    e.ev.levels.output = output;
    iaxc_post_event(e);
}

void iaxc_do_state_callback(int callNo)
{  
      iaxc_event e;   
      if(callNo < 0 || callNo >= nCalls) return;
      e.type = IAXC_EVENT_STATE;
      e.ev.call.callNo = callNo;
      e.ev.call.state = calls[callNo].state;
      e.ev.call.format = calls[callNo].format;
      strncpy(e.ev.call.remote,        calls[callNo].remote,        IAXC_EVENT_BUFSIZ);
      strncpy(e.ev.call.remote_name,   calls[callNo].remote_name,   IAXC_EVENT_BUFSIZ);
      strncpy(e.ev.call.local,         calls[callNo].local,         IAXC_EVENT_BUFSIZ);
      strncpy(e.ev.call.local_context, calls[callNo].local_context, IAXC_EVENT_BUFSIZ);
      iaxc_post_event(e);
}

void iaxc_do_registration_callback(int id, int reply, int msgcount) 
{
    iaxc_event e;
    e.type = IAXC_EVENT_REGISTRATION;
    e.ev.reg.id = id;
    e.ev.reg.reply = reply;
    e.ev.reg.msgcount = msgcount;
    iaxc_post_event(e);
}

static int iaxc_remove_registration_by_id(int id) {
	struct iaxc_registration *curr, *prev;
	struct iax_session *unregsess=NULL;
	int count=0;
	for( prev=NULL, curr=registrations; curr != NULL; prev=curr, curr=curr->next ) {
		if( curr->id == id ) {
			count++;			
			if( curr->session != NULL )
				iax_destroy( curr->session );
			// Send unregister command first.
			unregsess = iax_session_new();
		    if(unregsess)
			{
				iax_register_release(unregsess,curr->host,curr->user,curr->pass,5);			
				iaxc_millisleep(100);
				iax_destroy(unregsess);
			}

			if( prev != NULL )
				prev->next = curr->next;
			else
				registrations = curr->next;
			free( curr );
			break;
		}
	}
	return count;
}

EXPORT int iaxc_first_free_call()  {
	int i;
	for(i=0;i<nCalls;i++) 
	    if(calls[i].state == IAXC_CALL_STATE_FREE) 
		return i;
	
	return -1;
}


static void iaxc_clear_call(int toDump)
{
      // XXX libiax should handle cleanup, I think..
      calls[toDump].state = IAXC_CALL_STATE_FREE;
      calls[toDump].format = 0;
      calls[toDump].session = NULL;
      iaxc_do_state_callback(toDump);
}

/* select a call.  */
/* XXX Locking??  Start/stop audio?? */
EXPORT int iaxc_select_call(int callNo) {

	// continue if already selected?
	//if(callNo == selected_call) return;

	if(callNo >= nCalls) {
		iaxc_usermsg(IAXC_ERROR, "Error: tried to select out_of_range call %d", callNo);
		return -1;
	}
  
        // callNo < 0 means no call selected (i.e. all on hold)
	if(callNo < 0) {
	    if (selected_call >= 0) {
	    	calls[selected_call].state &= ~IAXC_CALL_STATE_SELECTED;
		}
	    selected_call = callNo;
	    return 0;
	}
  
	// de-select and notify the old call if not also the new call	
	if(callNo != selected_call) {
	    if (selected_call >= 0) {
		    calls[selected_call].state &= ~IAXC_CALL_STATE_SELECTED;
		    iaxc_do_state_callback(selected_call);
		}
	    selected_call = callNo;
	    calls[selected_call].state |= IAXC_CALL_STATE_SELECTED;
	}


	// if it's an incoming call, and ringing, answer it.
	if( !(calls[selected_call].state & IAXC_CALL_STATE_OUTGOING) && 
	     (calls[selected_call].state & IAXC_CALL_STATE_RINGING)) {
	    iaxc_answer_call(selected_call);
	} else {
	// otherwise just update state (answer does this for us)
	  iaxc_do_state_callback(selected_call);
	}

	return 0;
}
	  
/* external API accessor */
EXPORT int iaxc_selected_call() {
	return selected_call;
}

EXPORT void iaxc_set_networking(iaxc_sendto_t st, iaxc_recvfrom_t rf) {
    iaxc_sendto = st;
    iaxc_recvfrom = rf;
}

static void jb_errf(const char *fmt, ...)
{
    va_list args;
    char buf[1024];

    va_start(args, fmt);
    vsnprintf(buf, 1024, fmt, args);
    va_end(args);

    iaxc_usermsg(IAXC_ERROR, buf);
}

static void jb_warnf(const char *fmt, ...)
{
    va_list args;
    char buf[1024];

    va_start(args, fmt);
    vsnprintf(buf, 1024, fmt, args);
    va_end(args);

    iaxc_usermsg(IAXC_NOTICE, buf);
}

static void jb_dbgf(const char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
}

static void setup_jb_output() {
      //jb_setoutput(jb_errf, jb_warnf, jb_dbgf);
      jb_setoutput(jb_errf, jb_warnf, NULL);
}

// Parameters:
// audType - Define whether audio is handled by library or externally
EXPORT int iaxc_initialize(int audType, int inCalls, short port) {
	int i;

	/* os-specific initializations: init gettimeofday fake stuff in
	 * Win32, etc) */
	os_init();

	setup_jb_output();

//	printf("Starting app");
	MUTEXINIT(&iaxc_lock);
#ifdef _POCKETPC_
	iaxc_sendto = sendto;
	iaxc_recvfrom = recvfrom;
#endif

	if(iaxc_sendto == sendto) {
	    if ( (port = iax_init(port) < 0)) {
		    iaxc_usermsg(IAXC_ERROR, "Fatal error: failed to initialize iax with port %d", port);
		    return -1;
	    }
	    netfd = iax_get_fd();
	} else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -