#include "api_stack.h" #define DEFAULT_USER_AGENT "IM-client/OMA1.0" PREF_NAMESPACE_START /* stack constructor */ stack::stack(int _id, nua_callback_f _callback) { if(!_callback) return; // initialize this->id = _id; this->callback = _callback; this->initialized = false; this->thread = NULL; this->nua = NULL; this->root = NULL; this->running = false; /* authentication */ displayname = NULL, public_id = NULL, private_id = NULL, realm = NULL, password = NULL, privacy = NULL, early_ims = false; /* Network */ pcscf = NULL, pcscf_port = 5060; /* Features */ smsip = true, oma_large_msg = true, oma_sip_im = true, gsma_is = true, gsma_vs = true; // initialize memory handling if( su_home_init(this->home) ) return; this->initialized = true; } /* stack destructor */ stack::~stack() { if(this->thread) CloseHandle(this->thread); } /* run main loop for processing of messages */ inline ERR stack::run() { if(this->initialized && !this->running && !this->thread) { #ifdef WIN32 DWORD threadId; this->thread = CreateThread(NULL, 0, ThreadRunner, this, 0, &threadId); for(int i=0; i<5; i++) { if(this->running) { return ERR_SUCCESS; } Sleep(1000); } return ERR_STACK_NOT_RUNNING; #else # error "must be implemented" #endif } return (!this->initialized ? ERR_STACK_NOT_INITIALIZED : (this->running? ERR_STACK_ALREADY_EXIST : ERR_GLOBAL_FAILURE)); } /* shutdown the stack */ inline ERR stack::shutdown() { if(this->running) { if(this->root) { su_root_break(this->root); return ERR_SUCCESS; } else { return ERR_GLOBAL_FAILURE; } } else { return ERR_STACK_NOT_RUNNING; } } /* event loop processing */ void stack::loop() { // initialize root object this->root = su_root_create(this); if(!this->root) { su_home_deinit(this->home); return; } // create NUA stack this->nua = nua_create(this->root, this->callback, this, NUTAG_USER_AGENT(DEFAULT_USER_AGENT), NUTAG_PROXY("sip:127.0.0.1:5060"), /* tags as necessary ...*/ TAG_NULL()); if (!this->nua) { su_root_destroy(this->root); su_home_deinit(this->home); return; } // FIXME this->running = true; // enter main loop for processing of messages su_root_run(this->root); // Release resources if(this->nua) { nua_shutdown(this->nua); //nua_destroy(this->nua); this->nua = NULL; } if(this->root) { su_root_destroy(this->root); this->root = NULL; } if(this->home) { su_home_deinit(this->home); } this->running = false; } #ifdef WIN32 /* static threads runner*/ DWORD WINAPI stack::ThreadRunner( void* magic ) { ((stack*)magic)->loop(); return 0; } #endif /* handle callback event*/ void stack::callback_handle(nua_event_t _event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]) { GET_DIALOG_BY_HANDLE(dlg, nh); if(dlg) { dlg->dialog_callback(_event, status, phrase, nua, magic, nh, hmagic, sip, tags); } else { } } PREF_NAMESPACE_END