diff --git a/trunk/doubango/doubango.vcproj b/trunk/doubango/doubango.vcproj index c603bcb5..7f629ee9 100644 --- a/trunk/doubango/doubango.vcproj +++ b/trunk/doubango/doubango.vcproj @@ -209,31 +209,31 @@ Name="sm" > @@ -245,10 +245,26 @@ RelativePath=".\src\api_engine.cxx" > - - + + + + + + + + + @@ -345,10 +361,26 @@ RelativePath=".\src\api_errors.h" > - - + + + + + + + + + #include #include +#include #include @@ -58,7 +60,8 @@ ERR engine_deinitialize() std::list::iterator iter = __stacks.begin(); for ( ; iter!=__stacks.end(); iter++ ) { - delete(*iter); + (*iter)->shutdown(); + //delete(*iter); } __stacks.clear(); @@ -77,14 +80,14 @@ ERR engine_stack_create(int stack_id) { return ERR_STACK_ALREADY_EXIST; } - stack* sk = new stack(stack_id, engine_callback); - if(sk->get_initialized()) + stack* stk = new stack(stack_id, engine_callback); + if(stk->get_initialized()) { - __stacks.push_back(sk); + __stacks.push_back(stk); } else { - delete sk; + delete stk; return ERR_STACK_NOT_INITIALIZED; } @@ -96,7 +99,15 @@ ERR engine_stack_run(int stack_id) { if(!__initialized) return ERR_ENGINE_NOT_INITIALIZED; - return ERR_NOT_IMPLEMENTED; + stack* stk = (stack*)engine_stack_find(stack_id); + if(stk) + { + return stk->run(); + } + else + { + return ERR_STACK_NOT_FOUND; + } } /* shutdown downs the stack with the specified id */ @@ -104,7 +115,15 @@ ERR engine_stack_shutdown(int stack_id) { if(!__initialized) return ERR_ENGINE_NOT_INITIALIZED; - return ERR_NOT_IMPLEMENTED; + stack* stk = (stack*)engine_stack_find(stack_id); + if(stk) + { + return stk->shutdown(); + } + else + { + return ERR_STACK_NOT_FOUND; + } } /* shutdown downs all stacks */ @@ -116,8 +135,10 @@ ERR engine_stack_shutdown_all(void) } /* find stack by id*/ -stack* engine_stack_find(int stack_id) +void* engine_stack_find(int stack_id) { + if(!__initialized) return NULL; + std::list::iterator iter = __stacks.begin(); iter = std::find_if( iter, __stacks.end(), std::bind2nd( pred_stack_find_by_id(), stack_id ) ); if(iter != __stacks.end()) @@ -128,17 +149,12 @@ stack* engine_stack_find(int stack_id) } /* engine callback*/ -void engine_callback(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[]) +void engine_callback(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[]) { - + ((stack*)magic)->callback_handle(event, status, phrase, nua, magic, + nh, hmagic, sip, tags); } #undef PSTACK diff --git a/trunk/doubango/src/api_engine.h b/trunk/doubango/src/api_engine.h index 0730ca1b..f95631e7 100644 --- a/trunk/doubango/src/api_engine.h +++ b/trunk/doubango/src/api_engine.h @@ -3,7 +3,6 @@ #include "pref.h" #include "api_errors.h" -#include "api_stack.h" PREF_NAMESPACE_START @@ -15,7 +14,7 @@ DOUBANGO_API_C ERR engine_stack_run(int stack_id); DOUBANGO_API_C ERR engine_stack_shutdown(int stack_id); DOUBANGO_API_C ERR engine_stack_shutdown_all(void); -stack* engine_stack_find(int stack_id); +void* engine_stack_find(int stack_id); PREF_NAMESPACE_END diff --git a/trunk/doubango/src/api_errors.h b/trunk/doubango/src/api_errors.h index 16f2100d..54b2c25c 100644 --- a/trunk/doubango/src/api_errors.h +++ b/trunk/doubango/src/api_errors.h @@ -20,8 +20,13 @@ typedef enum tag_ERR ERR_ENGINE_NOT_INITIALIZED, /* engine not initialized or initialization failed*/ ERR_ENGINE_ALREADY_INITIALIZED, /* engine have been already initialized */ + /* SIP DIALOG */ + ERR_SIP_DIALOG_UNKNOWN, + ERR_SIP_DIALOG_NOT_FOUND, /* dialog not found */ + /* STACK errors */ - ERR_STACK_ALREADY_EXIST, + ERR_STACK_NOT_FOUND, /* stack not found*/ + ERR_STACK_ALREADY_EXIST, /* state already exist */ ERR_STACK_NOT_INITIALIZED, /* stack not initialized or initialization failed*/ ERR_STACK_IS_INVALID, /* stack is in an invalide state (NULL, destroyed, locked, ...) */ ERR_STACK_NOT_RUNNING, /* operation failed because the stack is not running */ diff --git a/trunk/doubango/src/api_sip.cxx b/trunk/doubango/src/api_sip.cxx new file mode 100644 index 00000000..fc26b5ec --- /dev/null +++ b/trunk/doubango/src/api_sip.cxx @@ -0,0 +1,289 @@ +#include "api_sip.h" +#include "api_engine.h" +#include "api_stack.h" + +#include +#include // FIXME: remove +#include // FIXME: remove + +PREF_NAMESPACE_START + +#define GET_STACK(stack_id, stk) \ + stack* stk = (stack*)engine_stack_find(stack_id); \ + if(!stk) return ERR_STACK_NOT_FOUND; \ + if(!stk->get_initialized()) return ERR_STACK_NOT_INITIALIZED; \ + if(!stk->get_running()) return ERR_STACK_NOT_RUNNING; + +#define SAFE_FREE_HOME_PTR(home, ptr) { if(ptr){ su_free(home, ptr); } } + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// sip REGISTER +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* send sip register message */ +ERR sip_register(int stack_id) +{ + GET_STACK(stack_id, stk); + return stk->sip_register(); +} + +/* send sip unregister (register with expires=0) message*/ +ERR sip_unregister(int stack_id) +{ + GET_STACK(stack_id, stk); + return stk->sip_unregister(); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// sip MESSAGE +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* send sip register message */ +ERR sip_message(int stack_id, const char* dest_address, const char* content_type, const char* content) +{ + GET_STACK(stack_id, stk); + return stk->sip_message(dest_address, content_type, content); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// authentication +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ERR auth_set(int stack_id, const char* public_id, const char* private_id, const char* password, const char* realm) +{ + ERR error = ERR_SUCCESS; + if( !ERR_SUCCEED( (error = auth_set_public_id(stack_id, public_id)) ) ) return error; + if( !ERR_SUCCEED( (error = auth_set_private_id(stack_id, private_id)) ) ) return error; + if( !ERR_SUCCEED( (error = auth_set_password(stack_id, password)) ) ) return error; + if( !ERR_SUCCEED( (error = auth_set_realm(stack_id, realm)) ) ) return error; + + return error; +} + +ERR auth_set_displayname(int stack_id, const char* displayname) +{ + GET_STACK(stack_id, stk); + SAFE_FREE_HOME_PTR(stk->get_home(), stk->get_displayname()); + stk->set_displayname( su_strdup(stk->get_home(), displayname) ); + nua_set_params(stk->get_nua(), + NUTAG_M_DISPLAY(displayname), + TAG_NULL()); + return ERR_SUCCESS; +} + +ERR auth_set_public_id(int stack_id, const char* public_id) +{ + GET_STACK(stack_id, stk); + SAFE_FREE_HOME_PTR(stk->get_home(), stk->get_public_id()); + stk->set_public_id( su_strdup(stk->get_home(), public_id) ); + return ERR_SUCCESS; +} + +ERR auth_set_private_id(int stack_id, const char* private_id) +{ + GET_STACK(stack_id, stk); + SAFE_FREE_HOME_PTR(stk->get_home(), stk->get_private_id()); + stk->set_private_id( su_strdup(stk->get_home(), private_id) ); + return ERR_SUCCESS; +} + +ERR auth_set_preferred_id(int stack_id, const char* preferred_id) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR auth_set_password(int stack_id, const char* password) +{ + GET_STACK(stack_id, stk); + SAFE_FREE_HOME_PTR(stk->get_home(), stk->get_password()); + stk->set_password( su_strdup(stk->get_home(), password) ); + return ERR_SUCCESS; +} + +ERR auth_set_realm(int stack_id, const char* realm) +{ + GET_STACK(stack_id, stk); + SAFE_FREE_HOME_PTR(stk->get_home(), stk->get_realm()); + stk->set_realm( su_strdup(stk->get_home(), realm) ); + nua_set_params(stk->get_nua(), + AUTHTAG_REALM(realm), + TAG_NULL()); + return ERR_SUCCESS; +} + +ERR auth_set_operator_id(int stack_id, const char* operator_id) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR auth_set_amf(int stack_id, const char* amf) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR auth_set_privacy(int stack_id, const char* privacy) +{ + GET_STACK(stack_id, stk); + SAFE_FREE_HOME_PTR(stk->get_home(), stk->get_privacy()); + stk->set_privacy( su_strdup(stk->get_home(), privacy) ); + return ERR_SUCCESS; +} + +ERR auth_set_security_mechanism(int stack_id, const char* security_mechanism) +{ + return ERR_NOT_IMPLEMENTED; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// network +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ERR network_set(int stack_id, const char* pcscf_ip, int pcscf_port, const char* transport) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR network_set_pcscf(int stack_id, const char* pcscf_ip, int pcscf_port) +{ + GET_STACK(stack_id, stk); + char* pcscf = su_sprintf(stk->get_home(), "sip:%s:%d", pcscf_ip, pcscf_port); + nua_set_params(stk->get_nua(), + NUTAG_PROXY(pcscf), + NUTAG_OUTBOUND("no-validate"), + TAG_NULL()); + su_free(stk->get_home(), pcscf); + + return ERR_SUCCESS; +} + +ERR network_set_transport(int stack_id, const char* transport) +{ + return ERR_NOT_IMPLEMENTED; +} + +/* SIP Header: P-Access-Network-Info + RFC 3455 +*/ +ERR network_set_net_info(int stack_id, const char* net_info) +{ + return ERR_NOT_IMPLEMENTED; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// qos +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ERR qos_set_audio_bandwith(int stack_id, int audio_bandwith) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR qos_set_audio_dscp(int stack_id, int audio_dscp) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR qos_set_video_bandwith(int stack_id, int video_bandwith) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR qos_set_video_dscp(int stack_id, int video_dscp) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR qos_set_msrp_bandwith(int stack_id, int msrp_bandwith) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR qos_set_msrp_dscp(int stack_id, int msrp_dscp) +{ + return ERR_NOT_IMPLEMENTED; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ipsec +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ERR ipsec_set(int stack_id, const char* mode, const char* protocol, const char* auth_algo, const char* enc_algo) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR ipsec_set_mode(int stack_id, const char* mode) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR ipsec_set_protocol(int stack_id, const char* protocol) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR ipsec_set_auth_algo(int stack_id, const char* auth_algo) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR ipsec_set_enc_algo(int stack_id, const char* enc_algo) +{ + return ERR_NOT_IMPLEMENTED; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// tls +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ERR tls_set_priv_key_path(int stack_id, const char* priv_key_path) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR tls_set_pub_key_path(int stack_id, const char* pub_key_path) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR tls_set_cert_path(int stack_id, const char* cert_path) +{ + return ERR_NOT_IMPLEMENTED; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// sigcomp +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ERR sigcomp_set_comp_id(int stack_id, const char* comp_id) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR sigcomp_enable_sipdict(int stack_id, bool enable) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR sigcomp_enable_presdict(int stack_id, bool enable) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR sigcomp_set_dms(int stack_id, int dms) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR sigcomp_set_sms(int stack_id, int sms) +{ + return ERR_NOT_IMPLEMENTED; +} + +ERR sigcomp_set_cpb(int stack_id, int cpb) +{ + return ERR_NOT_IMPLEMENTED; +} + + +PREF_NAMESPACE_END \ No newline at end of file diff --git a/trunk/doubango/src/api_sip.h b/trunk/doubango/src/api_sip.h new file mode 100644 index 00000000..beb570c7 --- /dev/null +++ b/trunk/doubango/src/api_sip.h @@ -0,0 +1,81 @@ +#ifndef _DOUBANGO_API_SIP_REGISTRATION_H_ +#define _DOUBANGO_API_SIP_REGISTRATION_H_ + +#include "pref.h" +#include "api_errors.h" + +PREF_NAMESPACE_START + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// sip REGISTER +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DOUBANGO_API_C ERR sip_register(int stack_id); +DOUBANGO_API_C ERR sip_unregister(int stack_id); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// sip MESSAGE +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DOUBANGO_API_C ERR sip_message(int stack_id, const char* dest_address, const char* content_type, const char* content); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// authentication +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DOUBANGO_API_C ERR auth_set(int stack_id, const char* public_id, const char* private_id, const char* password, const char* realm); +DOUBANGO_API_C ERR auth_set_displayname(int stack_id, const char* displayname); +DOUBANGO_API_C ERR auth_set_public_id(int stack_id, const char* public_id); +DOUBANGO_API_C ERR auth_set_private_id(int stack_id, const char* private_id); +DOUBANGO_API_C ERR auth_set_preferred_id(int stack_id, const char* preferred_id); +DOUBANGO_API_C ERR auth_set_password(int stack_id, const char* password); +DOUBANGO_API_C ERR auth_set_realm(int stack_id, const char* realm); +DOUBANGO_API_C ERR auth_set_operator_id(int stack_id, const char* operator_id); +DOUBANGO_API_C ERR auth_set_amf(int stack_id, const char* amf); +DOUBANGO_API_C ERR auth_set_privacy(int stack_id, const char* privacy); +DOUBANGO_API_C ERR auth_set_security_mechanism(int stack_id, const char* security_mechanism); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// network +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DOUBANGO_API_C ERR network_set(int stack_id, const char* pcscf_ip, int pcscf_port, const char* transport); +DOUBANGO_API_C ERR network_set_pcscf(int stack_id, const char* pcscf_ip, int pcscf_port); +DOUBANGO_API_C ERR network_set_transport(int stack_id, const char* transport); +DOUBANGO_API_C ERR network_set_net_info(int stack_id, const char* net_info); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// qos +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DOUBANGO_API_C ERR qos_set_audio_bandwith(int stack_id, int audio_bandwith); +DOUBANGO_API_C ERR qos_set_audio_dscp(int stack_id, int audio_dscp); +DOUBANGO_API_C ERR qos_set_video_bandwith(int stack_id, int video_bandwith); +DOUBANGO_API_C ERR qos_set_video_dscp(int stack_id, int video_dscp); +DOUBANGO_API_C ERR qos_set_msrp_bandwith(int stack_id, int msrp_bandwith); +DOUBANGO_API_C ERR qos_set_msrp_dscp(int stack_id, int msrp_dscp); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ipsec +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DOUBANGO_API_C ERR ipsec_set(int stack_id, const char* mode, const char* protocol, const char* auth_algo, const char* enc_algo); +DOUBANGO_API_C ERR ipsec_set_mode(int stack_id, const char* mode); +DOUBANGO_API_C ERR ipsec_set_protocol(int stack_id, const char* protocol); +DOUBANGO_API_C ERR ipsec_set_auth_algo(int stack_id, const char* auth_algo); +DOUBANGO_API_C ERR ipsec_set_enc_algo(int stack_id, const char* enc_algo); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// tls +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DOUBANGO_API_C ERR tls_set_priv_key_path(int stack_id, const char* priv_key_path); +DOUBANGO_API_C ERR tls_set_pub_key_path(int stack_id, const char* pub_key_path); +DOUBANGO_API_C ERR tls_set_cert_path(int stack_id, const char* cert_path); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// sigcomp +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DOUBANGO_API_C ERR sigcomp_set_comp_id(int stack_id, const char* comp_id); +DOUBANGO_API_C ERR sigcomp_enable_sipdict(int stack_id, bool enable); +DOUBANGO_API_C ERR sigcomp_enable_presdict(int stack_id, bool enable); +DOUBANGO_API_C ERR sigcomp_set_dms(int stack_id, int dms); +DOUBANGO_API_C ERR sigcomp_set_sms(int stack_id, int sms); +DOUBANGO_API_C ERR sigcomp_set_cpb(int stack_id, int cpb); + +PREF_NAMESPACE_END + +#endif /* _DOUBANGO_API_SIP_REGISTRATION_H_ */ \ No newline at end of file diff --git a/trunk/doubango/src/api_sip_states.h b/trunk/doubango/src/api_sip_states.h new file mode 100644 index 00000000..0987da0d --- /dev/null +++ b/trunk/doubango/src/api_sip_states.h @@ -0,0 +1,31 @@ +#ifndef _DOUBANGO_SIP_STATES_H_ +#define _DOUBANGO_SIP_STATES_H_ + +#include "pref.h" + +PREF_NAMESPACE_START + +typedef enum tag_SIP_STATE +{ + SS_UNKNOWN_UNKNOWN, + + /* REGISTER */ + SS_REGISTER_UNKNOWN, + SS_REGISTER_INITIALIZED, + SS_REGISTER_TRYING, + SS_REGISTER_AUTHENTIFYING, + SS_REGISTER_ESTABLISHED, + SS_REGISTER_TERMINATED, + + /* MESSAGE */ + SS_MESSAGE_UNKNOWN, + SS_MESSAGE_INITIALIZED, + SS_MESSAGE_TRYING, + SS_MESSAGE_AUTHENTIFYING, + SS_MESSAGE_TERMINATED, +} +SIP_STATE; + +PREF_NAMESPACE_END + +#endif /* _DOUBANGO_SIP_STATES_H_ */ \ No newline at end of file diff --git a/trunk/doubango/src/api_stack.cxx b/trunk/doubango/src/api_stack.cxx index df8a0d0d..961e9096 100644 --- a/trunk/doubango/src/api_stack.cxx +++ b/trunk/doubango/src/api_stack.cxx @@ -1,13 +1,93 @@ #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): id(_id), initialized(false) +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, pcscf_ip = 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) @@ -17,7 +97,9 @@ stack::stack(int _id, nua_callback_f callback): id(_id), initialized(false) } // create NUA stack - this->nua = nua_create(this->root, callback, this, + 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) @@ -27,43 +109,55 @@ stack::stack(int _id, nua_callback_f callback): id(_id), initialized(false) return; } - // set necessary parameters - nua_set_params(this->nua, - /* tags as necessary ...*/ - TAG_NULL()); + // FIXME + this->running = true; // enter main loop for processing of messages su_root_run(this->root); - this->initialized = true; + // 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; } -/* stack destructor */ -stack::~stack() +#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[]) { - if(this->initialized) + GET_DIALOG_BY_HANDLE(dlg, nh); + if(dlg) + { + dlg->dialog_callback(_event, status, phrase, nua, magic, + nh, hmagic, sip, tags); + } + else { - // destroy NUA stack - nua_destroy(this->nua); - - // deinit root object - su_root_destroy(this->root); - - // deinitialize memory handling - su_home_deinit(this->home); } } -/* gets the stack id */ -inline int stack::get_id()const -{ - return this->id; -} - -/* returns true if initialized, false otherwise */ -inline bool stack::get_initialized() const -{ - return this->initialized; -} - PREF_NAMESPACE_END \ No newline at end of file diff --git a/trunk/doubango/src/api_stack.h b/trunk/doubango/src/api_stack.h index dca41c8d..f3112b8f 100644 --- a/trunk/doubango/src/api_stack.h +++ b/trunk/doubango/src/api_stack.h @@ -2,28 +2,146 @@ #define __DOUBANGO_STACK_H__ #include "pref.h" +#include "api_errors.h" +#include "sip_dialog.h" #include +#include +#include + PREF_NAMESPACE_START +/* generate setter and getter methods*/ +#define DEFINE_GET_SET(type, member)\ + inline type &get_##member(){ return this->##member; } \ + inline void set_##member(type val){ this->##member = val; } + +/* predicate: find dialog by handle */ +struct pred_dialog_find_by_handle: public std::binary_function< sip_dialog*, nua_handle_t*, bool > { + bool operator () ( const sip_dialog* dlg, const nua_handle_t* handle ) const { + return dlg->get_handle() == handle; + } +}; +/* predicate: find dialog by sipmethod */ +struct pred_dialog_find_by_sipmethod: public std::binary_function< sip_dialog*, const char*, bool > { + bool operator () ( const sip_dialog* dlg, const char* sipmethod ) const { + return !stricmp(dlg->get_sipmethod(), sipmethod); + } +}; +/* predicate: find all dialogs in terminated state */ +//==> IN C++ bool isDlgTerminated(const sip_dialog* dlg){ return dlg->get_terminated(); } +#define GET_DIALOG_TERMINATED(dlg)\ + sip_dialog* dlg = NULL; \ + std::list::iterator iter = std::find_if( this->dialogs.begin(), this->dialogs.end(), isDlgTerminated ); \ + if(iter != this->dialogs.end()) dlg = *iter; + +/* find dialog by sipmethod*/ +#define GET_DIALOG_BY_SIPMETHOD(dlg, sipmethod) \ + sip_dialog* dlg = NULL; \ + std::list::iterator iter = std::find_if( this->dialogs.begin(), this->dialogs.end(), std::bind2nd( pred_dialog_find_by_sipmethod(), sipmethod ) ); \ + if(iter != this->dialogs.end()) dlg = *iter; + +/* find dialog by handle */ +#define GET_DIALOG_BY_HANDLE(dlg, handle) \ + sip_dialog* dlg = NULL; \ + std::list::iterator iter = std::find_if( this->dialogs.begin(), this->dialogs.end(), std::bind2nd( pred_dialog_find_by_handle(), handle ) ); \ + if(iter != this->dialogs.end()) dlg = *iter; + class DOUBANGO_API stack { public: stack(int id, nua_callback_f callback); ~stack(); - inline int get_id() const; - inline bool get_initialized() const; + inline ERR run(); + inline ERR shutdown(); + + inline int get_id() const { return this->id; } + inline bool get_running() const { return this->running; } + inline bool get_initialized() const { return this->initialized; } + inline su_home_t* get_home() { return this->home; } + inline nua_t* get_nua() { return this->nua; } + + // + // SIP + // + ERR sip_register(); + ERR sip_unregister(); + + ERR sip_message(const char* dest_address, const char* content_type, const char* content); + + + // + // Authentication + // + DEFINE_GET_SET(char*, displayname); + DEFINE_GET_SET(char*, public_id); + DEFINE_GET_SET(char*, private_id); + DEFINE_GET_SET(char*, realm); + DEFINE_GET_SET(char*, password); + DEFINE_GET_SET(char*, privacy); + DEFINE_GET_SET(char*, pcscf_ip); + DEFINE_GET_SET(int, pcscf_port); + + // + // Features + // + DEFINE_GET_SET(bool, smsip); + DEFINE_GET_SET(bool, oma_large_msg); + DEFINE_GET_SET(bool, oma_sip_im); + DEFINE_GET_SET(bool, gsma_is); + DEFINE_GET_SET(bool, gsma_vs); + + void 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[]); +private: +#ifdef WIN32 + static DWORD WINAPI ThreadRunner( void* magic ); +#endif + void loop(); private: int id; bool initialized; + bool running; + + nua_callback_f callback; + void* thread; + + std::listdialogs; su_home_t home[1]; /* memory home */ su_root_t *root; /* root object */ nua_t *nua; /* NUA stack object */ + + // + // Authentication + // + char* displayname; + char* public_id; + char* private_id; + char* realm; + char* password; + char* privacy; + char* pcscf_ip; + int pcscf_port; + + // + // Features + // + bool smsip; + bool oma_large_msg; + bool oma_sip_im; + bool gsma_is; + bool gsma_vs; }; +#undef DEFINE_GET_SET + PREF_NAMESPACE_END #endif /* __DOUBANGO_STACK_H__ */ \ No newline at end of file diff --git a/trunk/doubango/src/api_stack_sip.cxx b/trunk/doubango/src/api_stack_sip.cxx new file mode 100644 index 00000000..f887bd1e --- /dev/null +++ b/trunk/doubango/src/api_stack_sip.cxx @@ -0,0 +1,41 @@ +#include "api_stack.h" +#include "sip_dialog_register.h" +#include "sip_dialog_message.h" +//#include + +PREF_NAMESPACE_START + +/* SIP REGISTER*/ +ERR stack::sip_register() +{ + GET_DIALOG_BY_SIPMETHOD(dlg, "REGISTER"); + if(dlg){ + return ((sip_dialog_register*)dlg)->Start(); + } + else{ + sip_dialog_register* dlg_register = new sip_dialog_register(this); + this->dialogs.push_back(dlg_register); + return dlg_register->Start(); + } +} + +/* SIP UNREGISTER */ +ERR stack::sip_unregister() +{ + GET_DIALOG_BY_SIPMETHOD(dlg, "REGISTER"); + if(dlg){ + return ((sip_dialog_register*)dlg)->Stop(); + } + else return ERR_SIP_DIALOG_NOT_FOUND; +} + +/* SIP MESSAGE */ +ERR stack::sip_message(const char* dest_address, const char* content_type, const char* content) +{ + sip_dialog_message* dlg_message = new sip_dialog_message(this, dest_address, content_type, content); + this->dialogs.push_back(dlg_message); + return dlg_message->Start(); +} + + +PREF_NAMESPACE_END \ No newline at end of file diff --git a/trunk/doubango/src/doubango.h b/trunk/doubango/src/doubango.h index c17ff2f5..e4c9dba3 100644 --- a/trunk/doubango/src/doubango.h +++ b/trunk/doubango/src/doubango.h @@ -31,6 +31,7 @@ extern "C" { #include "api_engine.h" + #include "api_sip.h" } #endif /* __DOUBANGO_DOUBANGO_H__ */ \ No newline at end of file diff --git a/trunk/doubango/src/pref.h b/trunk/doubango/src/pref.h index 4058d6ad..7f538417 100644 --- a/trunk/doubango/src/pref.h +++ b/trunk/doubango/src/pref.h @@ -47,7 +47,7 @@ /* disable warnings */ #ifdef WIN32 -#pragma warning( disable : 4132 4100 4127 4152 4355 4996) +#pragma warning( disable : 4132 4100 4127 4152 4355 4996 4251) #endif /* namespace definition*/ diff --git a/trunk/doubango/src/sip_dialog.cxx b/trunk/doubango/src/sip_dialog.cxx index 25e66c32..3183adac 100644 --- a/trunk/doubango/src/sip_dialog.cxx +++ b/trunk/doubango/src/sip_dialog.cxx @@ -29,8 +29,10 @@ PREF_NAMESPACE_START /* sip_dialog constructor */ -sip_dialog::sip_dialog() +sip_dialog::sip_dialog(stack* _stk) { + this->handle = NULL; + this->stk = _stk; } /* sip_dialog destructor*/ @@ -38,4 +40,11 @@ sip_dialog::~sip_dialog() { } +/* called when dialog state change*/ +void sip_dialog::OnStateChanged(SIP_STATE state) +{ + this->state_current = state; + SU_DEBUG_3(("%s::OnStateChanged ==> %d\n", this->get_sipmethod(), state)); +} + PREF_NAMESPACE_END \ No newline at end of file diff --git a/trunk/doubango/src/sip_dialog.h b/trunk/doubango/src/sip_dialog.h index 0cded47d..4247afaa 100644 --- a/trunk/doubango/src/sip_dialog.h +++ b/trunk/doubango/src/sip_dialog.h @@ -29,14 +29,46 @@ #define __DOUBANGO_DIALOG_SM_H__ #include "pref.h" +#include "api_sip_states.h" +#include "api_errors.h" + +#include +#include +#include PREF_NAMESPACE_START -class sip_dialog +class stack; + +class DOUBANGO_API sip_dialog { public: - sip_dialog(); + sip_dialog(stack* stk); ~sip_dialog(); + + inline nua_handle_t* get_handle() const{ return this->handle; } + inline void set_handle(nua_handle_t* h) { this->handle = h; } + + inline SIP_STATE get_state_current() const{ return this->state_current; } + inline void set_state_current(SIP_STATE s) { this->state_current = s; } + + virtual ERR Start() = 0; + virtual ERR Stop() = 0; + virtual void OnStateChanged(SIP_STATE state); + virtual inline const char* get_sipmethod()const = 0; + virtual inline bool get_terminated()const = 0; + virtual void dialog_callback(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[]) = 0; + + +protected: + nua_handle_t* handle; + stack* stk; + SIP_STATE state_current; }; PREF_NAMESPACE_END diff --git a/trunk/doubango/src/sip_dialog_info.cxx b/trunk/doubango/src/sip_dialog_info.cxx index 6afb81fd..7be36075 100644 --- a/trunk/doubango/src/sip_dialog_info.cxx +++ b/trunk/doubango/src/sip_dialog_info.cxx @@ -29,8 +29,8 @@ PREF_NAMESPACE_START /* sip_dialog_info constructor*/ -sip_dialog_info::sip_dialog_info() -:sm_ctx(*this) +sip_dialog_info::sip_dialog_info(stack* stk) +:sip_dialog(stk), sm_ctx(*this) { } diff --git a/trunk/doubango/src/sip_dialog_info.h b/trunk/doubango/src/sip_dialog_info.h index 9d4a522c..5438ca33 100644 --- a/trunk/doubango/src/sip_dialog_info.h +++ b/trunk/doubango/src/sip_dialog_info.h @@ -38,7 +38,7 @@ PREF_NAMESPACE_START class sip_dialog_info : public sip_dialog { public: - sip_dialog_info(); + sip_dialog_info(stack* stk); ~sip_dialog_info(); private: diff --git a/trunk/doubango/src/sip_dialog_invite.cxx b/trunk/doubango/src/sip_dialog_invite.cxx index 2b5d1e7c..3691afd0 100644 --- a/trunk/doubango/src/sip_dialog_invite.cxx +++ b/trunk/doubango/src/sip_dialog_invite.cxx @@ -29,8 +29,8 @@ PREF_NAMESPACE_START /* sip_dialog_invite constructor*/ -sip_dialog_invite::sip_dialog_invite() -:sm_ctx(*this) +sip_dialog_invite::sip_dialog_invite(stack* stk) +:sip_dialog(stk),sm_ctx(*this) { } diff --git a/trunk/doubango/src/sip_dialog_invite.h b/trunk/doubango/src/sip_dialog_invite.h index 49edd720..41c0f0e4 100644 --- a/trunk/doubango/src/sip_dialog_invite.h +++ b/trunk/doubango/src/sip_dialog_invite.h @@ -38,7 +38,7 @@ PREF_NAMESPACE_START class sip_dialog_invite : public sip_dialog { public: - sip_dialog_invite(); + sip_dialog_invite(stack* stk); ~sip_dialog_invite(); private: diff --git a/trunk/doubango/src/sip_dialog_message.cxx b/trunk/doubango/src/sip_dialog_message.cxx index 763bffaa..da5a292b 100644 --- a/trunk/doubango/src/sip_dialog_message.cxx +++ b/trunk/doubango/src/sip_dialog_message.cxx @@ -25,18 +25,99 @@ * */ #include "sip_dialog_message.h" +#include "api_stack.h" PREF_NAMESPACE_START /* sip_dialog_message constructor*/ -sip_dialog_message::sip_dialog_message() -:sm_ctx(*this) +sip_dialog_message::sip_dialog_message(stack* stk, const char* _dest_address, const char* _content_type, const char* _content) +:sip_dialog(stk),sm_ctx(*this) { + this->dest_address = su_strdup(this->stk->get_home(), _dest_address); + this->content_type = su_strdup(this->stk->get_home(), _content_type); + this->content = su_strdup(this->stk->get_home(), _content); } /* sip_dialog_message destructor */ sip_dialog_message::~sip_dialog_message() { + // FIXME: destroy handle + su_free(this->stk->get_home(), this->dest_address); + su_free(this->stk->get_home(), this->content_type); + su_free(this->stk->get_home(), this->content); } +/* start sending MESSAGE */ +ERR sip_dialog_message::Start() +{ + this->handle = nua_handle(this->stk->get_nua(), this->stk->get_home(), + SIPTAG_TO_STR(this->dest_address), TAG_END()); + + if(!this->handle) + { + return ERR_GLOBAL_FAILURE; + } + + nua_message(this->handle, + SIPTAG_CONTENT_TYPE_STR(this->content_type), + SIPTAG_PAYLOAD_STR(this->content), + TAG_END()); + + this->sm_ctx.sm_messageSent(); + + return ERR_SUCCESS; +} + +/* terminate/stop dialog */ +ERR sip_dialog_message::Stop() +{ + return ERR_NOT_IMPLEMENTED; +} + +/* dialog state changed */ +void sip_dialog_message::OnStateChanged(SIP_STATE state) +{ + sip_dialog::OnStateChanged(state); +} + +/* get sip method */ +inline const char* sip_dialog_message::get_sipmethod()const +{ + return "MESSAGE"; +} + +/* returns true if terminated and false otherwise*/ +inline bool sip_dialog_message::get_terminated()const +{ + return (this->state_current == SS_MESSAGE_TERMINATED); +} + +/* dialog callback */ +void sip_dialog_message::dialog_callback(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[]) +{ + switch(_event) + { + case nua_r_message: + { + if(status <200) this->sm_ctx.sm_1xx_response(); + else if(status <300) this->sm_ctx.sm_2xx_response(); + else if(status == 401 || status == 407 || status == 421 || status == 494) this->sm_ctx.sm_401_407_421_494_response(); + else this->sm_ctx.sm_unsupported_response(); + + break; + } + + default: + { + break; + } + } +} + + PREF_NAMESPACE_END \ No newline at end of file diff --git a/trunk/doubango/src/sip_dialog_message.h b/trunk/doubango/src/sip_dialog_message.h index c5e079c2..e1bd8f70 100644 --- a/trunk/doubango/src/sip_dialog_message.h +++ b/trunk/doubango/src/sip_dialog_message.h @@ -35,14 +35,31 @@ PREF_NAMESPACE_START /* MESSAGE */ -class sip_dialog_message : public sip_dialog +class DOUBANGO_API sip_dialog_message : public sip_dialog { public: - sip_dialog_message(); + sip_dialog_message(stack* stk, const char* dest_address, const char* content_type, const char* content); ~sip_dialog_message(); + /* sip_dialog override*/ + ERR Start(); + ERR Stop(); + void OnStateChanged(SIP_STATE state); + inline const char* get_sipmethod()const; + inline bool get_terminated()const; + void dialog_callback(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[]); + private: sip_dialog_messageContext sm_ctx; + + char* dest_address; + char* content_type; + char* content; }; PREF_NAMESPACE_END diff --git a/trunk/doubango/src/sip_dialog_options.cxx b/trunk/doubango/src/sip_dialog_options.cxx index a77ccff1..93c3caf6 100644 --- a/trunk/doubango/src/sip_dialog_options.cxx +++ b/trunk/doubango/src/sip_dialog_options.cxx @@ -30,8 +30,8 @@ PREF_NAMESPACE_START /* sip_dialog_message constructor*/ -sip_dialog_options::sip_dialog_options() -:sm_ctx(*this) +sip_dialog_options::sip_dialog_options(stack* stk) +:sip_dialog(stk),sm_ctx(*this) { } diff --git a/trunk/doubango/src/sip_dialog_options.h b/trunk/doubango/src/sip_dialog_options.h index 70ae702b..e5e86cca 100644 --- a/trunk/doubango/src/sip_dialog_options.h +++ b/trunk/doubango/src/sip_dialog_options.h @@ -38,7 +38,7 @@ PREF_NAMESPACE_START class sip_dialog_options : public sip_dialog { public: - sip_dialog_options(); + sip_dialog_options(stack* stk); ~sip_dialog_options(); private: diff --git a/trunk/doubango/src/sip_dialog_publish.cxx b/trunk/doubango/src/sip_dialog_publish.cxx index 71dc2c52..50502b55 100644 --- a/trunk/doubango/src/sip_dialog_publish.cxx +++ b/trunk/doubango/src/sip_dialog_publish.cxx @@ -29,8 +29,8 @@ PREF_NAMESPACE_START /* sip_dialog_publish constructor*/ -sip_dialog_publish::sip_dialog_publish() -:sm_ctx(*this) +sip_dialog_publish::sip_dialog_publish(stack* stk) +:sip_dialog(stk),sm_ctx(*this) { } diff --git a/trunk/doubango/src/sip_dialog_publish.h b/trunk/doubango/src/sip_dialog_publish.h index 5ac68849..735ea862 100644 --- a/trunk/doubango/src/sip_dialog_publish.h +++ b/trunk/doubango/src/sip_dialog_publish.h @@ -38,7 +38,7 @@ PREF_NAMESPACE_START class sip_dialog_publish : public sip_dialog { public: - sip_dialog_publish(); + sip_dialog_publish(stack* stk); ~sip_dialog_publish(); private: diff --git a/trunk/doubango/src/sip_dialog_register.cxx b/trunk/doubango/src/sip_dialog_register.cxx index a04e62ff..69697a35 100644 --- a/trunk/doubango/src/sip_dialog_register.cxx +++ b/trunk/doubango/src/sip_dialog_register.cxx @@ -25,18 +25,116 @@ * */ #include "sip_dialog_register.h" +#include "api_stack.h" PREF_NAMESPACE_START /* sip_dialog_register constructor*/ -sip_dialog_register::sip_dialog_register() -:sm_ctx(*this) +sip_dialog_register::sip_dialog_register(stack* stk) +:sip_dialog(stk),sm_ctx(*this) { + } /* sip_dialog_register destructor */ sip_dialog_register::~sip_dialog_register() { + // FIXME: destroy handle +} + +/* start */ +ERR sip_dialog_register::Start() +{ + this->sm_ctx.enterStartState(); + + this->handle = nua_handle(this->stk->get_nua(), this->stk->get_home(), + SIPTAG_TO_STR(this->stk->get_realm()), TAG_END()); + + if(!this->handle) + { + return ERR_GLOBAL_FAILURE; + } + + nua_register(this->handle, + SIPTAG_PRIVACY_STR(this->stk->get_privacy()), + NUTAG_OUTBOUND("no-options-keepalive"), + NUTAG_OUTBOUND("no-validate"), + NUTAG_KEEPALIVE(0), + SIPTAG_EXPIRES_STR("20"), + //NUTAG_M_USERNAME("doubango"), + SIPTAG_FROM_STR(this->stk->get_public_id()), + SIPTAG_TO_STR(this->stk->get_public_id()), + NUTAG_M_FEATURES("audio"), + NUTAG_CALLEE_CAPS(0), + SIPTAG_SUPPORTED_STR("timer, precondition, path, replaces, 100rel, gruu"), + + + //NUTAG_M_FEATURES("+g.3gpp.smsip;+g.3gpp.cs-voice"), + //TAG_IF(this->gsma_vs, NUTAG_M_FEATURES("+g.3gpp.cs-voice")), + + TAG_END()); + this->sm_ctx.sm_registerSent(); + + return ERR_SUCCESS; +} + +/* stop */ +ERR sip_dialog_register::Stop() +{ + if(this->handle) + { + nua_unregister(this->handle, TAG_END()); + this->sm_ctx.sm_unregisterSent(); + + return ERR_SUCCESS; + } + else return ERR_SIP_DIALOG_UNKNOWN; +} + +/* state changed */ +void sip_dialog_register::OnStateChanged(SIP_STATE state) +{ + sip_dialog::OnStateChanged(state); +} + +/* sip method name */ +inline const char* sip_dialog_register::get_sipmethod()const +{ + return "REGISTER"; +} + +/* returns true if terminated and false otherwise*/ +inline bool sip_dialog_register::get_terminated()const +{ + return (this->state_current == SS_REGISTER_TERMINATED); +} + +/* dialog callback function*/ +void sip_dialog_register::dialog_callback(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[]) +{ + switch(_event) + { + case nua_r_register: + case nua_r_unregister: + { + if(status <200) this->sm_ctx.sm_1xx_response(); + else if(status <300) this->sm_ctx.sm_2xx_response(); + else if(status == 401 || status == 407 || status == 421 || status == 494) this->sm_ctx.sm_401_407_421_494_response(); + else this->sm_ctx.sm_unsupported_response(); + + break; + } + + default: + { + break; + } + } } PREF_NAMESPACE_END \ No newline at end of file diff --git a/trunk/doubango/src/sip_dialog_register.h b/trunk/doubango/src/sip_dialog_register.h index aed5ab77..eec3ffeb 100644 --- a/trunk/doubango/src/sip_dialog_register.h +++ b/trunk/doubango/src/sip_dialog_register.h @@ -35,14 +35,32 @@ PREF_NAMESPACE_START /* REGISTER */ -class sip_dialog_register : public sip_dialog +class DOUBANGO_API sip_dialog_register : public sip_dialog { public: - sip_dialog_register(); + sip_dialog_register(stack* stk); ~sip_dialog_register(); + /* sip_dialog override*/ + ERR Start(); + ERR Stop(); + void OnStateChanged(SIP_STATE state); + inline const char* get_sipmethod()const; + inline bool get_terminated()const; + void dialog_callback(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[]); + + + bool get_registering() { return this->registering; } + void set_registering(bool val) { this->registering = val; } + private: sip_dialog_registerContext sm_ctx; + bool registering; }; PREF_NAMESPACE_END diff --git a/trunk/doubango/src/sip_dialog_subscribe.cxx b/trunk/doubango/src/sip_dialog_subscribe.cxx index 24001e13..7a22fe39 100644 --- a/trunk/doubango/src/sip_dialog_subscribe.cxx +++ b/trunk/doubango/src/sip_dialog_subscribe.cxx @@ -29,8 +29,8 @@ PREF_NAMESPACE_START /* sip_dialog_subscribe constructor*/ -sip_dialog_subscribe::sip_dialog_subscribe() -:sm_ctx(*this) +sip_dialog_subscribe::sip_dialog_subscribe(stack* stk) +:sip_dialog(stk),sm_ctx(*this) { } diff --git a/trunk/doubango/src/sip_dialog_subscribe.h b/trunk/doubango/src/sip_dialog_subscribe.h index 505e2f5b..03a9f7b4 100644 --- a/trunk/doubango/src/sip_dialog_subscribe.h +++ b/trunk/doubango/src/sip_dialog_subscribe.h @@ -38,7 +38,7 @@ PREF_NAMESPACE_START class sip_dialog_subscribe : public sip_dialog { public: - sip_dialog_subscribe(); + sip_dialog_subscribe(stack* stk); ~sip_dialog_subscribe(); private: diff --git a/trunk/doubango/src/sm_dialog_message_sm.cxx b/trunk/doubango/src/sm_dialog_message_sm.cxx index 13024191..65b387a8 100644 --- a/trunk/doubango/src/sm_dialog_message_sm.cxx +++ b/trunk/doubango/src/sm_dialog_message_sm.cxx @@ -43,11 +43,151 @@ namespace dgo { // Static class declarations. map_dialog_message_Initialized map_dialog_message::Initialized("map_dialog_message::Initialized", 0); + map_dialog_message_Trying map_dialog_message::Trying("map_dialog_message::Trying", 1); + map_dialog_message_Authentifying map_dialog_message::Authentifying("map_dialog_message::Authentifying", 2); + map_dialog_message_Terminated map_dialog_message::Terminated("map_dialog_message::Terminated", 3); + + void sip_dialog_messageState::sm_1xx_response(sip_dialog_messageContext& context) + { + Default(context); + return; + } + + void sip_dialog_messageState::sm_2xx_response(sip_dialog_messageContext& context) + { + Default(context); + return; + } + + void sip_dialog_messageState::sm_401_407_421_494_response(sip_dialog_messageContext& context) + { + Default(context); + return; + } + + void sip_dialog_messageState::sm_messageSent(sip_dialog_messageContext& context) + { + Default(context); + return; + } + + void sip_dialog_messageState::sm_unsupported_response(sip_dialog_messageContext& context) + { + Default(context); + return; + } void sip_dialog_messageState::Default(sip_dialog_messageContext& context) { assert(1==0); + return; + } + + void map_dialog_message_Default::sm_401_407_421_494_response(sip_dialog_messageContext& context) + { + + (context.getState()).Exit(context); + context.setState(map_dialog_message::Authentifying); + (context.getState()).Entry(context); + + return; + } + + void map_dialog_message_Default::Default(sip_dialog_messageContext& context) + { + + + return; + } + + void map_dialog_message_Initialized::Entry(sip_dialog_messageContext& context) + +{ + sip_dialog_message& ctxt(context.getOwner()); + + ctxt.OnStateChanged(SS_MESSAGE_INITIALIZED); + return; + } + + void map_dialog_message_Initialized::sm_messageSent(sip_dialog_messageContext& context) + { + + (context.getState()).Exit(context); + context.setState(map_dialog_message::Trying); + (context.getState()).Entry(context); + + return; + } + + void map_dialog_message_Trying::Entry(sip_dialog_messageContext& context) + +{ + sip_dialog_message& ctxt(context.getOwner()); + + ctxt.OnStateChanged(SS_MESSAGE_TRYING); + return; + } + + void map_dialog_message_Trying::sm_1xx_response(sip_dialog_messageContext& context) + { + + + return; + } + + void map_dialog_message_Trying::sm_2xx_response(sip_dialog_messageContext& context) + { + + (context.getState()).Exit(context); + context.setState(map_dialog_message::Terminated); + (context.getState()).Entry(context); + + return; + } + + void map_dialog_message_Trying::sm_401_407_421_494_response(sip_dialog_messageContext& context) + { + + (context.getState()).Exit(context); + context.setState(map_dialog_message::Authentifying); + (context.getState()).Entry(context); + + return; + } + + void map_dialog_message_Trying::sm_unsupported_response(sip_dialog_messageContext& context) + { + + (context.getState()).Exit(context); + context.setState(map_dialog_message::Terminated); + (context.getState()).Entry(context); + + return; + } + + void map_dialog_message_Authentifying::Entry(sip_dialog_messageContext& context) + +{ + sip_dialog_message& ctxt(context.getOwner()); + + ctxt.OnStateChanged(SS_MESSAGE_AUTHENTIFYING); + return; + } + + void map_dialog_message_Terminated::Entry(sip_dialog_messageContext& context) + +{ + sip_dialog_message& ctxt(context.getOwner()); + + ctxt.OnStateChanged(SS_MESSAGE_TERMINATED); + return; + } + + void map_dialog_message_Terminated::Default(sip_dialog_messageContext& context) + { + + return; } } diff --git a/trunk/doubango/src/sm_dialog_message_sm.h b/trunk/doubango/src/sm_dialog_message_sm.h index 402aa926..d6a14911 100644 --- a/trunk/doubango/src/sm_dialog_message_sm.h +++ b/trunk/doubango/src/sm_dialog_message_sm.h @@ -20,6 +20,9 @@ namespace dgo // Forward declarations. class map_dialog_message; class map_dialog_message_Initialized; + class map_dialog_message_Trying; + class map_dialog_message_Authentifying; + class map_dialog_message_Terminated; class map_dialog_message_Default; class sip_dialog_messageState; class sip_dialog_messageContext; @@ -37,6 +40,11 @@ namespace dgo virtual void Entry(sip_dialog_messageContext&) {}; virtual void Exit(sip_dialog_messageContext&) {}; + virtual void sm_1xx_response(sip_dialog_messageContext& context); + virtual void sm_2xx_response(sip_dialog_messageContext& context); + virtual void sm_401_407_421_494_response(sip_dialog_messageContext& context); + virtual void sm_messageSent(sip_dialog_messageContext& context); + virtual void sm_unsupported_response(sip_dialog_messageContext& context); protected: @@ -48,6 +56,9 @@ namespace dgo public: static map_dialog_message_Initialized Initialized; + static map_dialog_message_Trying Trying; + static map_dialog_message_Authentifying Authentifying; + static map_dialog_message_Terminated Terminated; }; class map_dialog_message_Default : @@ -59,6 +70,8 @@ namespace dgo : sip_dialog_messageState(name, stateId) {}; + virtual void sm_401_407_421_494_response(sip_dialog_messageContext& context); + virtual void Default(sip_dialog_messageContext& context); }; class map_dialog_message_Initialized : @@ -69,6 +82,46 @@ namespace dgo : map_dialog_message_Default(name, stateId) {}; + void Entry(sip_dialog_messageContext&); + void sm_messageSent(sip_dialog_messageContext& context); + }; + + class map_dialog_message_Trying : + public map_dialog_message_Default + { + public: + map_dialog_message_Trying(const char *name, int stateId) + : map_dialog_message_Default(name, stateId) + {}; + + void Entry(sip_dialog_messageContext&); + void sm_1xx_response(sip_dialog_messageContext& context); + void sm_2xx_response(sip_dialog_messageContext& context); + void sm_401_407_421_494_response(sip_dialog_messageContext& context); + void sm_unsupported_response(sip_dialog_messageContext& context); + }; + + class map_dialog_message_Authentifying : + public map_dialog_message_Default + { + public: + map_dialog_message_Authentifying(const char *name, int stateId) + : map_dialog_message_Default(name, stateId) + {}; + + void Entry(sip_dialog_messageContext&); + }; + + class map_dialog_message_Terminated : + public map_dialog_message_Default + { + public: + map_dialog_message_Terminated(const char *name, int stateId) + : map_dialog_message_Default(name, stateId) + {}; + + void Entry(sip_dialog_messageContext&); + void Default(sip_dialog_messageContext& context); }; class sip_dialog_messageContext : @@ -107,6 +160,31 @@ namespace dgo return (dynamic_cast(*_state)); }; + void sm_1xx_response() + { + (getState()).sm_1xx_response(*this); + }; + + void sm_2xx_response() + { + (getState()).sm_2xx_response(*this); + }; + + void sm_401_407_421_494_response() + { + (getState()).sm_401_407_421_494_response(*this); + }; + + void sm_messageSent() + { + (getState()).sm_messageSent(*this); + }; + + void sm_unsupported_response() + { + (getState()).sm_unsupported_response(*this); + }; + private: sip_dialog_message& _owner; diff --git a/trunk/doubango/src/sm_dialog_register_sm.cxx b/trunk/doubango/src/sm_dialog_register_sm.cxx index 4f92f4a7..1c6cc0ff 100644 --- a/trunk/doubango/src/sm_dialog_register_sm.cxx +++ b/trunk/doubango/src/sm_dialog_register_sm.cxx @@ -43,11 +43,213 @@ namespace dgo { // Static class declarations. map_dialog_register_Initialized map_dialog_register::Initialized("map_dialog_register::Initialized", 0); + map_dialog_register_Trying map_dialog_register::Trying("map_dialog_register::Trying", 1); + map_dialog_register_Established map_dialog_register::Established("map_dialog_register::Established", 2); + map_dialog_register_Authentifying map_dialog_register::Authentifying("map_dialog_register::Authentifying", 3); + map_dialog_register_Terminated map_dialog_register::Terminated("map_dialog_register::Terminated", 4); + + void sip_dialog_registerState::sm_1xx_response(sip_dialog_registerContext& context) + { + Default(context); + return; + } + + void sip_dialog_registerState::sm_2xx_response(sip_dialog_registerContext& context) + { + Default(context); + return; + } + + void sip_dialog_registerState::sm_401_407_421_494_response(sip_dialog_registerContext& context) + { + Default(context); + return; + } + + void sip_dialog_registerState::sm_registerSent(sip_dialog_registerContext& context) + { + Default(context); + return; + } + + void sip_dialog_registerState::sm_unregisterSent(sip_dialog_registerContext& context) + { + Default(context); + return; + } + + void sip_dialog_registerState::sm_unsupported_response(sip_dialog_registerContext& context) + { + Default(context); + return; + } void sip_dialog_registerState::Default(sip_dialog_registerContext& context) { assert(1==0); + return; + } + + void map_dialog_register_Default::sm_401_407_421_494_response(sip_dialog_registerContext& context) + { + + (context.getState()).Exit(context); + context.setState(map_dialog_register::Authentifying); + (context.getState()).Entry(context); + + return; + } + + void map_dialog_register_Default::Default(sip_dialog_registerContext& context) + { + + + return; + } + + void map_dialog_register_Initialized::Entry(sip_dialog_registerContext& context) + +{ + sip_dialog_register& ctxt(context.getOwner()); + + ctxt.OnStateChanged(SS_REGISTER_INITIALIZED); + return; + } + + void map_dialog_register_Initialized::sm_registerSent(sip_dialog_registerContext& context) + { + sip_dialog_register& ctxt(context.getOwner()); + + (context.getState()).Exit(context); + context.clearState(); + try + { + ctxt.set_registering(true); + context.setState(map_dialog_register::Trying); + } + catch (...) + { + context.setState(map_dialog_register::Trying); +} + (context.getState()).Entry(context); + + return; + } + + void map_dialog_register_Trying::Entry(sip_dialog_registerContext& context) + +{ + sip_dialog_register& ctxt(context.getOwner()); + + ctxt.OnStateChanged(SS_REGISTER_TRYING); + return; + } + + void map_dialog_register_Trying::sm_1xx_response(sip_dialog_registerContext& context) + { + + + return; + } + + void map_dialog_register_Trying::sm_2xx_response(sip_dialog_registerContext& context) + { + sip_dialog_register& ctxt(context.getOwner()); + + if (ctxt.get_registering() == true) + { + (context.getState()).Exit(context); + // No actions. + context.setState(map_dialog_register::Established); + (context.getState()).Entry(context); + } + else if (ctxt.get_registering() == false) + + { + (context.getState()).Exit(context); + // No actions. + context.setState(map_dialog_register::Terminated); + (context.getState()).Entry(context); + } else + { + map_dialog_register_Default::sm_2xx_response(context); + } + + return; + } + + void map_dialog_register_Trying::sm_401_407_421_494_response(sip_dialog_registerContext& context) + { + + (context.getState()).Exit(context); + context.setState(map_dialog_register::Authentifying); + (context.getState()).Entry(context); + + return; + } + + void map_dialog_register_Trying::sm_unsupported_response(sip_dialog_registerContext& context) + { + + (context.getState()).Exit(context); + context.setState(map_dialog_register::Terminated); + (context.getState()).Entry(context); + + return; + } + + void map_dialog_register_Established::Entry(sip_dialog_registerContext& context) + +{ + sip_dialog_register& ctxt(context.getOwner()); + + ctxt.OnStateChanged(SS_REGISTER_ESTABLISHED); + return; + } + + void map_dialog_register_Established::sm_unregisterSent(sip_dialog_registerContext& context) + { + sip_dialog_register& ctxt(context.getOwner()); + + (context.getState()).Exit(context); + context.clearState(); + try + { + ctxt.set_registering(false); + context.setState(map_dialog_register::Trying); + } + catch (...) + { + context.setState(map_dialog_register::Trying); +} + (context.getState()).Entry(context); + + return; + } + + void map_dialog_register_Authentifying::Entry(sip_dialog_registerContext& context) + +{ + sip_dialog_register& ctxt(context.getOwner()); + + ctxt.OnStateChanged(SS_REGISTER_AUTHENTIFYING); + return; + } + + void map_dialog_register_Terminated::Entry(sip_dialog_registerContext& context) + +{ + sip_dialog_register& ctxt(context.getOwner()); + + ctxt.OnStateChanged(SS_REGISTER_TERMINATED); + return; + } + + void map_dialog_register_Terminated::Default(sip_dialog_registerContext& context) + { + + return; } } diff --git a/trunk/doubango/src/sm_dialog_register_sm.h b/trunk/doubango/src/sm_dialog_register_sm.h index cbf63d18..32621e02 100644 --- a/trunk/doubango/src/sm_dialog_register_sm.h +++ b/trunk/doubango/src/sm_dialog_register_sm.h @@ -20,6 +20,10 @@ namespace dgo // Forward declarations. class map_dialog_register; class map_dialog_register_Initialized; + class map_dialog_register_Trying; + class map_dialog_register_Established; + class map_dialog_register_Authentifying; + class map_dialog_register_Terminated; class map_dialog_register_Default; class sip_dialog_registerState; class sip_dialog_registerContext; @@ -37,6 +41,12 @@ namespace dgo virtual void Entry(sip_dialog_registerContext&) {}; virtual void Exit(sip_dialog_registerContext&) {}; + virtual void sm_1xx_response(sip_dialog_registerContext& context); + virtual void sm_2xx_response(sip_dialog_registerContext& context); + virtual void sm_401_407_421_494_response(sip_dialog_registerContext& context); + virtual void sm_registerSent(sip_dialog_registerContext& context); + virtual void sm_unregisterSent(sip_dialog_registerContext& context); + virtual void sm_unsupported_response(sip_dialog_registerContext& context); protected: @@ -48,6 +58,10 @@ namespace dgo public: static map_dialog_register_Initialized Initialized; + static map_dialog_register_Trying Trying; + static map_dialog_register_Established Established; + static map_dialog_register_Authentifying Authentifying; + static map_dialog_register_Terminated Terminated; }; class map_dialog_register_Default : @@ -59,6 +73,8 @@ namespace dgo : sip_dialog_registerState(name, stateId) {}; + virtual void sm_401_407_421_494_response(sip_dialog_registerContext& context); + virtual void Default(sip_dialog_registerContext& context); }; class map_dialog_register_Initialized : @@ -69,6 +85,58 @@ namespace dgo : map_dialog_register_Default(name, stateId) {}; + void Entry(sip_dialog_registerContext&); + void sm_registerSent(sip_dialog_registerContext& context); + }; + + class map_dialog_register_Trying : + public map_dialog_register_Default + { + public: + map_dialog_register_Trying(const char *name, int stateId) + : map_dialog_register_Default(name, stateId) + {}; + + void Entry(sip_dialog_registerContext&); + void sm_1xx_response(sip_dialog_registerContext& context); + void sm_2xx_response(sip_dialog_registerContext& context); + void sm_401_407_421_494_response(sip_dialog_registerContext& context); + void sm_unsupported_response(sip_dialog_registerContext& context); + }; + + class map_dialog_register_Established : + public map_dialog_register_Default + { + public: + map_dialog_register_Established(const char *name, int stateId) + : map_dialog_register_Default(name, stateId) + {}; + + void Entry(sip_dialog_registerContext&); + void sm_unregisterSent(sip_dialog_registerContext& context); + }; + + class map_dialog_register_Authentifying : + public map_dialog_register_Default + { + public: + map_dialog_register_Authentifying(const char *name, int stateId) + : map_dialog_register_Default(name, stateId) + {}; + + void Entry(sip_dialog_registerContext&); + }; + + class map_dialog_register_Terminated : + public map_dialog_register_Default + { + public: + map_dialog_register_Terminated(const char *name, int stateId) + : map_dialog_register_Default(name, stateId) + {}; + + void Entry(sip_dialog_registerContext&); + void Default(sip_dialog_registerContext& context); }; class sip_dialog_registerContext : @@ -107,6 +175,36 @@ namespace dgo return (dynamic_cast(*_state)); }; + void sm_1xx_response() + { + (getState()).sm_1xx_response(*this); + }; + + void sm_2xx_response() + { + (getState()).sm_2xx_response(*this); + }; + + void sm_401_407_421_494_response() + { + (getState()).sm_401_407_421_494_response(*this); + }; + + void sm_registerSent() + { + (getState()).sm_registerSent(*this); + }; + + void sm_unregisterSent() + { + (getState()).sm_unregisterSent(*this); + }; + + void sm_unsupported_response() + { + (getState()).sm_unsupported_response(*this); + }; + private: sip_dialog_register& _owner; diff --git a/trunk/rfcs.txt b/trunk/rfcs.txt new file mode 100644 index 00000000..c46bf364 --- /dev/null +++ b/trunk/rfcs.txt @@ -0,0 +1,55 @@ +RFC 3261 +RFC 2617 +RFC 3262 +RFC 3263 +RFC 3265 +RFC 2806 +RFC 2976 +RFC 3311 +RFC 3313 +RFC 3323 +RFC 3326 +RFC 3325 +RFC 3327 + RFC 3329 +RFC 3361 +RFC 3420 +RFC 3428 +RFC 3486 +RFC 3515 +RFC 2327 +RFC 3581 +RFC 3608 +RFC 3680 +RFC 3824 +RFC 3840 +RFC 3841 +RFC 3842 +RFC 3856 +RFC 3857 +RFC 3858 +RFC 3859 +RFC 3860 +RFC 3891 +RFC 3892 +RFC 3903 +RFC 4028 +RFC 4168 +RFC 4320 +RFC 4488 +RFC 5057 +RFC 4566 +RFC 3264 +RFC 3266 +RFC 3312 +RFC 3388 +RFC 3407 +RFC 3524 +RFC 3551 +RFC 3556 +RFC 3605 +RFC 3890 +RFC 3455 +draft-ietf-sip-outbound +draft-ietf-sip-gruu-14 + diff --git a/trunk/test/test.cpp b/trunk/test/test.cpp index c01cfe6c..f7f420ea 100644 --- a/trunk/test/test.cpp +++ b/trunk/test/test.cpp @@ -4,6 +4,10 @@ #include "stdafx.h" #include +#ifdef WIN32 +#include +#endif + #define STACK_ID 1234 int _tmain(int argc, _TCHAR* argv[]) @@ -12,9 +16,25 @@ int _tmain(int argc, _TCHAR* argv[]) assert( ERR_SUCCEED(dgo::engine_stack_create(STACK_ID)) ); assert( ERR_SUCCEED(dgo::engine_stack_run(STACK_ID)) ); + + //Sleep(1000); + + assert( ERR_SUCCEED(dgo::auth_set(STACK_ID, "sip:doubango@wonderland.net", "doubango", "doubango", "wonderland.net" )) ); + assert( ERR_SUCCEED(dgo::auth_set_privacy(STACK_ID, "none")) ); + assert( ERR_SUCCEED(dgo::auth_set_displayname(STACK_ID, "My display Name")) ); + assert( ERR_SUCCEED(dgo::network_set_pcscf(STACK_ID, "192.168.0.14", 5060)) ); + + assert( ERR_SUCCEED(dgo::sip_register(STACK_ID)) ); + Sleep(1000); + assert( ERR_SUCCEED(dgo::sip_message(STACK_ID, "sip:toto@wonderland.net", "text/plain", "test")) ); + Sleep(50000); + assert( ERR_SUCCEED(dgo::sip_unregister(STACK_ID)) ); + Sleep(5000); assert( ERR_SUCCEED(dgo::engine_deinitialize()) ); + Sleep(5000); + // FIXME:http://209.85.229.132/search?q=cache:8_OFeYfRS9EJ:fisheye.freeswitch.org/browse/~raw,r%3D14993/FreeSWITCH/src/mod/endpoints/mod_sofia/sofia_reg.c+nua_unregister&cd=7&hl=en&ct=clnk return 0; }