From: <st...@us...> - 2003-06-17 22:53:31
|
Update of /cvsroot/iaxclient/iaxclient/lib In directory sc8-pr-cvs1:/tmp/cvs-serv6863/lib Modified Files: iaxclient.h iaxclient_lib.c iaxclient_lib.h Log Message: Another big commit: 1) Replace the "RadioBox" control with a ListCntrl control, for the call list. This has expandable columns, and displays each data type in it's own column. 2) Some locking for the library: try to prevent us from doing the processing loop while moving the calls around from the front-end. 3) REGISTRATION, and better incoming call support. Incoming calls now are not auto-answered, but are answered when you select them. You can register with an IAX server (tested for IAX1 only so far). Index: iaxclient.h =================================================================== RCS file: /cvsroot/iaxclient/iaxclient/lib/iaxclient.h,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- iaxclient.h 16 Jun 2003 23:01:29 -0000 1.12 +++ iaxclient.h 17 Jun 2003 22:53:27 -0000 1.13 @@ -50,8 +50,9 @@ #define IAXC_CALL_STATE_FREE 0 #define IAXC_CALL_STATE_ACTIVE (1<<1) #define IAXC_CALL_STATE_OUTGOING (1<<2) -#define IAXC_CALL_STATE_COMPLETE (1<<3) -#define IAXC_CALL_STATE_SELECTED (1<<4) +#define IAXC_CALL_STATE_RINGING (1<<3) +#define IAXC_CALL_STATE_COMPLETE (1<<4) +#define IAXC_CALL_STATE_SELECTED (1<<5) #define IAXC_TEXT_TYPE_STATUS 1 #define IAXC_TEXT_TYPE_NOTICE 2 @@ -97,6 +98,7 @@ int iaxc_start_processing_thread(); int iaxc_stop_processing_thread(); void iaxc_call(char *num); +void iaxc_register(char *user, char *pass, char *host); void iaxc_answer_call(int callNo); void iaxc_dump_call(void); void iaxc_reject_call(void); Index: iaxclient_lib.c =================================================================== RCS file: /cvsroot/iaxclient/iaxclient/lib/iaxclient_lib.c,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- iaxclient_lib.c 17 Jun 2003 02:06:42 -0000 1.22 +++ iaxclient_lib.c 17 Jun 2003 22:53:27 -0000 1.23 @@ -6,10 +6,25 @@ #include <varargs.h> #endif +struct iaxc_registration { + struct iax_session *session; + int firstpass; + struct timeval last; + char host[256]; + char user[256]; + char pass[256]; + long refresh; + struct iaxc_registration *next; +}; + +struct iaxc_registration *registrations = NULL; + static int iAudioType; static int iEncodeType; +MUTEX iaxc_lock; + int netfd; int port; int c, i; @@ -23,7 +38,6 @@ struct timeval lastouttm; -static struct iaxc_call * find_call(struct iax_session *session); static void do_iax_event(); static THREAD procThread; @@ -162,15 +176,26 @@ } if(selected_call >= 0) { - calls[selected_call].state &= ~IAXC_CALL_STATE_SELECTED; - iaxc_do_state_callback(selected_call); + calls[selected_call].state &= ~IAXC_CALL_STATE_SELECTED; + iaxc_do_state_callback(selected_call); } - calls[callNo].state |= IAXC_CALL_STATE_SELECTED; - selected_call = callNo; - iaxc_do_state_callback(selected_call); + if(callNo >= 0) { + calls[callNo].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); + } + // should do callback to say all are unselected... + } } /* external API accessor */ @@ -187,6 +212,8 @@ * Win32, etc) */ os_init(); + MUTEXINIT(&iaxc_lock); + if ( (port = iax_init(0) < 0)) { iaxc_usermsg(IAXC_ERROR, "Fatal error: failed to initialize iax with port %d", port); return -1; @@ -234,6 +261,7 @@ pa_shutdown_audio(); break; } + MUTEXDESTROY(&iaxc_lock); } @@ -243,16 +271,43 @@ iax_set_formats(fmt); } +void iaxc_refresh_registrations() { + struct iaxc_registration *cur; + struct timeval now; + + gettimeofday(&now,NULL); + + for(cur = registrations; cur != NULL; cur=cur->next) { + if(iaxc_usecdiff(&now, &cur->last) > cur->refresh ) { + fprintf(stderr, "refreshing registration %s:%s@%s\n", + cur->host, cur->user, cur->pass, 300); + + cur->session = iax_session_new(); + if(!cur->session) { + iaxc_usermsg(IAXC_ERROR, "Can't make new registration session"); + return; + } + + iax_register(cur->session, cur->host, cur->user, cur->pass, 300); + cur->last = now; + } + } +} + void iaxc_process_calls(void) { #ifdef USE_WIN_AUDIO - win_flush_audio_output_buffers(); - if (iAudioType == AUDIO_INTERNAL) { - win_prepare_audio_buffers(); - } + win_flush_audio_output_buffers(); + if (iAudioType == AUDIO_INTERNAL) { + win_prepare_audio_buffers(); + } #endif - iaxc_service_network(netfd); - service_audio(); + MUTEXLOCK(&iaxc_lock); + iaxc_service_network(netfd); + service_audio(); + iaxc_refresh_registrations(); + + MUTEXUNLOCK(&iaxc_lock); } THREADFUNCDECL(iaxc_processor) @@ -395,13 +450,18 @@ iaxc_clear_call(callNo); break; case IAX_EVENT_ACCEPT: - calls[callNo].state |= IAXC_CALL_STATE_COMPLETE; + calls[callNo].state |= IAXC_CALL_STATE_RINGING; iaxc_do_state_callback(callNo); iaxc_usermsg(IAXC_STATUS,"Call %d ringing", callNo); // issue_prompt(f); break; case IAX_EVENT_ANSWER: - iaxc_answer_call(callNo); + calls[callNo].state &= ~IAXC_CALL_STATE_RINGING; + calls[callNo].state |= IAXC_CALL_STATE_COMPLETE; + iaxc_do_state_callback(callNo); + iaxc_usermsg(IAXC_STATUS,"Call %d answered", callNo); + //iaxc_answer_call(callNo); + // notify the user? break; case IAX_EVENT_VOICE: handle_audio_event(e, callNo); @@ -414,6 +474,39 @@ } } +void iaxc_register(char *user, char *pass, char *host) +{ + struct iaxc_registration *newreg; + + newreg = malloc(sizeof (struct iaxc_registration)); + if(!newreg) { + iaxc_usermsg(IAXC_ERROR, "Can't make new registration"); + return; + } + + newreg->session = iax_session_new(); + if(!newreg->session) { + iaxc_usermsg(IAXC_ERROR, "Can't make new registration session"); + return; + } + + gettimeofday(&newreg->last,NULL); + newreg->refresh = 60*1000*1000; // 60 seconds, in usecs + + strncpy(newreg->host, host, 256); + strncpy(newreg->user, user, 256); + strncpy(newreg->pass, pass, 256); + + // so we notify the user. + newreg->firstpass = 1; + + // send out the initial registration timeout 300 seconds + iax_register(newreg->session, host, user, pass, 300); + + // add it to the list; + newreg->next = registrations; + registrations = newreg; +} void iaxc_call(char *num) { @@ -454,34 +547,42 @@ void iaxc_answer_call(int callNo) { - iax_answer(calls[selected_call].session); + fprintf(stderr, "iaxc answering call %d\n", callNo); + calls[callNo].state |= IAXC_CALL_STATE_COMPLETE; + calls[callNo].state &= ~IAXC_CALL_STATE_RINGING; + iax_answer(calls[callNo].session); + iaxc_do_state_callback(callNo); } void iaxc_dump_call(void) { int toDump = selected_call; - if(toDump < 0) - { - iaxc_usermsg(IAXC_ERROR, "Error: tried to dump but no call selected"); - return; + MUTEXLOCK(&iaxc_lock); + if(toDump < 0) { + iaxc_usermsg(IAXC_ERROR, "Error: tried to dump but no call selected"); + } else { + iax_hangup(calls[selected_call].session,"Dumped Call"); + iaxc_usermsg(IAXC_STATUS, "Hanging up call %d", toDump); + iaxc_clear_call(toDump); } - - iax_hangup(calls[selected_call].session,"Dumped Call"); - iaxc_usermsg(IAXC_STATUS, "Hanging up call %d", toDump); - iaxc_clear_call(toDump); + MUTEXUNLOCK(&iaxc_lock); } void iaxc_reject_call(void) { + MUTEXLOCK(&iaxc_lock); // XXX should take callNo? iax_reject(calls[selected_call].session, "Call rejected manually."); iaxc_clear_call(selected_call); + MUTEXUNLOCK(&iaxc_lock); } void iaxc_send_dtmf(char digit) { + MUTEXLOCK(&iaxc_lock); if(selected_call >= 0) iax_send_dtmf(calls[selected_call].session,digit); + MUTEXUNLOCK(&iaxc_lock); } static int iaxc_find_call_by_session(struct iax_session *session) @@ -520,19 +621,69 @@ do_iax_event(); /* do pending event if any */ } +static void iaxc_handle_regreply(struct iax_event *e) { + struct iaxc_registration *cur; + // find the registration session + + for(cur = registrations; cur != NULL; cur=cur->next) + if(cur->session == e->session) break; + + if(!cur) { + iaxc_usermsg(IAXC_ERROR, "Unexpected registration reply"); + return; + } + + if(cur->firstpass) { + cur->firstpass = 0; + +#ifdef IAXC_IAX2 + if(e->etype == IAX_EVENT_REGACK ) { + iaxc_usermsg(IAXC_STATUS, "Registration accepted"); + } else if(e->etype == IAX_EVENT_REGREJ ) { + iaxc_usermsg(IAXC_STATUS, "Registration rejected"); + } +#else // IAX1 + + if(e->event.regreply.status == IAX_REG_SUCCESS) + iaxc_usermsg(IAXC_STATUS, "Registration accepted"); + else if(e->event.regreply.status == IAX_REG_REJECT) + iaxc_usermsg(IAXC_STATUS, "Registration rejected"); + // XXX should remove from registrations list? + else if(e->event.regreply.status == IAX_REG_TIMEOUT) + iaxc_usermsg(IAXC_STATUS, "Registration timed out"); + else + iaxc_usermsg(IAXC_ERROR, "Unknown registration event"); +#endif + } + + // XXX I think the session is no longer valid.. at least, that's + // what miniphone does, and re-using the session doesn't seem to + // work! + cur->session = NULL; +} + + static void do_iax_event() { struct iax_event *e = 0; int callNo; + struct iax_session *session; while ( (e = iax_get_event(0))) { + // first, see if this is an event for one of our calls. callNo = iaxc_find_call_by_session(e->session); if(callNo >= 0) { iaxc_handle_network_event(e, callNo); - iax_event_free(e); - } else { - if(e->etype != IAX_EVENT_CONNECT) { - iaxc_usermsg(IAXC_STATUS, "Huh? This is an event for a non-existant session?"); - } + } else if +#ifndef IAXC_IAX2 + ( e->etype == IAX_EVENT_REGREP ) +#else + ((e->etype == IAX_EVENT_REGACK ) || (e->etype == IAX_EVENT_REGREJ )) +#endif + { + iaxc_handle_regreply(e); + } else if(e->etype == IAX_EVENT_REGREQ ) { + iaxc_usermsg(IAXC_ERROR, "Registration requested by someone, but we don't understand!"); + } else if(e->etype == IAX_EVENT_CONNECT) { callNo = iaxc_next_free_call(); @@ -540,6 +691,7 @@ iaxc_usermsg(IAXC_STATUS, "Incoming Call, but no appearances"); // XXX Reject this call!, or just ignore? iax_reject(e->session, "Too many calls, we're busy!"); + goto bail; } #ifndef IAXC_IAX2 @@ -576,7 +728,7 @@ calls[callNo].gsmin = 0; calls[callNo].gsmout = 0; calls[callNo].session = e->session; - calls[callNo].state = IAXC_CALL_STATE_ACTIVE; + calls[callNo].state = IAXC_CALL_STATE_ACTIVE|IAXC_CALL_STATE_RINGING; // should we even accept? or, we accept, but @@ -584,11 +736,15 @@ iax_accept(calls[callNo].session); iax_ring_announce(calls[callNo].session); - // should we select this call? - iaxc_select_call(callNo); + iaxc_do_state_callback(callNo); + iaxc_usermsg(IAXC_STATUS, "Incoming call on line %d", callNo); - iax_event_free(e); + + } else { + iaxc_usermsg(IAXC_STATUS, "Event (type %d) for a non-existant session. Dropping", e->etype); } +bail: + iax_event_free(e); } } Index: iaxclient_lib.h =================================================================== RCS file: /cvsroot/iaxclient/iaxclient/lib/iaxclient_lib.h,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- iaxclient_lib.h 16 Jun 2003 23:01:29 -0000 1.16 +++ iaxclient_lib.h 17 Jun 2003 22:53:28 -0000 1.17 @@ -112,6 +112,7 @@ extern double iaxc_silence_threshold; extern int iaxc_audio_output_mode; extern iaxc_event_callback_t iaxc_event_callback; +extern MUTEX iaxc_lock; /* external audio functions */ void iaxc_external_service_audio(); |