From 8ffe9121e25f700d605432ad4b3fa7e26c84a938 Mon Sep 17 00:00:00 2001 From: bossiel Date: Mon, 7 Jun 2010 15:53:02 +0000 Subject: [PATCH] Update support for QoS preconditions (RFC 3312). --- trunk/bindings/_common/SipMessage.cxx | 2 +- .../vs_2005/csharp/test/Form1.Designer.cs | 25 +++ trunk/bindings/vs_2005/csharp/test/Form1.cs | 28 +++ .../tinyMEDIA/include/tinymedia/tmedia_qos.h | 10 +- .../include/tinymedia/tmedia_session.h | 4 + trunk/tinyMEDIA/src/tmedia_qos.c | 187 +++++++++++++++++- trunk/tinyMEDIA/src/tmedia_session.c | 39 ++++ trunk/tinyMEDIA/src/tmedia_session_dummy.c | 36 ++++ trunk/tinyMEDIA/src/tmedia_session_ghost.c | 1 + trunk/tinyMEDIA/test/test_qos.h | 183 ++++++++++++++++- trunk/tinySIP/include/tinysip/tsip_ssession.h | 22 ++- trunk/tinySIP/include/tinysip_config.h | 2 +- trunk/tinySIP/test/test_sipmessages.h | 1 + .../tinyXCAP/include/tinyxcap/txcap_action.h | 2 +- trunk/vs_2005/tinyDEMO/tinyDEMO.sln | 16 ++ trunk/vs_2005/tinyDEMO/tinyDEMO.vcproj | 4 +- trunk/vs_2005/tinyMEDIA/test.vcproj | 4 + 17 files changed, 552 insertions(+), 14 deletions(-) diff --git a/trunk/bindings/_common/SipMessage.cxx b/trunk/bindings/_common/SipMessage.cxx index a39b9a98..6d5c5959 100644 --- a/trunk/bindings/_common/SipMessage.cxx +++ b/trunk/bindings/_common/SipMessage.cxx @@ -97,7 +97,7 @@ const tsip_header_t* SipMessage::getSipHeader(const char* name, unsigned index / tsk_list_foreach(item, this->sipmessage->headers){ - if(tsk_striequals(tsip_header_get_name_2(TSIP_HEADER(item)), name)){ + if(tsk_striequals(tsip_header_get_name_2(TSIP_HEADER(item->data)), name)){ if(pos++ >= index){ hdr = (const tsip_header_t*)item->data; break; diff --git a/trunk/bindings/vs_2005/csharp/test/Form1.Designer.cs b/trunk/bindings/vs_2005/csharp/test/Form1.Designer.cs index 4716462a..deea4828 100644 --- a/trunk/bindings/vs_2005/csharp/test/Form1.Designer.cs +++ b/trunk/bindings/vs_2005/csharp/test/Form1.Designer.cs @@ -33,6 +33,8 @@ namespace test this.textBoxDebug = new System.Windows.Forms.TextBox(); this.buttonPublish = new System.Windows.Forms.Button(); this.buttonUnPublish = new System.Windows.Forms.Button(); + this.buttonUnSub = new System.Windows.Forms.Button(); + this.buttonSub = new System.Windows.Forms.Button(); this.SuspendLayout(); // // buttonRegister @@ -83,11 +85,32 @@ namespace test this.buttonUnPublish.UseVisualStyleBackColor = true; this.buttonUnPublish.Click += new System.EventHandler(this.buttonUnPublish_Click); // + // buttonUnSub + // + this.buttonUnSub.Location = new System.Drawing.Point(199, 206); + this.buttonUnSub.Name = "buttonUnSub"; + this.buttonUnSub.Size = new System.Drawing.Size(75, 23); + this.buttonUnSub.TabIndex = 6; + this.buttonUnSub.Text = "UnSubscribe"; + this.buttonUnSub.UseVisualStyleBackColor = true; + // + // buttonSub + // + this.buttonSub.Location = new System.Drawing.Point(12, 205); + this.buttonSub.Name = "buttonSub"; + this.buttonSub.Size = new System.Drawing.Size(75, 23); + this.buttonSub.TabIndex = 5; + this.buttonSub.Text = "Subscribe"; + this.buttonSub.UseVisualStyleBackColor = true; + this.buttonSub.Click += new System.EventHandler(this.buttonSub_Click); + // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(286, 374); + this.Controls.Add(this.buttonUnSub); + this.Controls.Add(this.buttonSub); this.Controls.Add(this.buttonUnPublish); this.Controls.Add(this.buttonPublish); this.Controls.Add(this.textBoxDebug); @@ -107,6 +130,8 @@ namespace test private System.Windows.Forms.TextBox textBoxDebug; private System.Windows.Forms.Button buttonPublish; private System.Windows.Forms.Button buttonUnPublish; + private System.Windows.Forms.Button buttonUnSub; + private System.Windows.Forms.Button buttonSub; } } diff --git a/trunk/bindings/vs_2005/csharp/test/Form1.cs b/trunk/bindings/vs_2005/csharp/test/Form1.cs index b0790a7c..06dd4393 100644 --- a/trunk/bindings/vs_2005/csharp/test/Form1.cs +++ b/trunk/bindings/vs_2005/csharp/test/Form1.cs @@ -24,6 +24,7 @@ namespace test RegistrationSession regSession = null; PublicationSession pubSession = null; + SubscriptionSession subSession = null; MyCallback callback = null; SipStack stack = null; @@ -145,6 +146,19 @@ namespace test { this.textBoxDebug.Text = text; } + + private void buttonSub_Click(object sender, EventArgs e) + { + if (this.subSession == null) + { + this.subSession = new SubscriptionSession(stack); + this.subSession.addHeader("Accept", "application/reginfo+xml"); + this.subSession.addHeader("Event", "reg"); + this.subSession.setExpires(30); + + this.subSession.Subscribe(); + } + } } @@ -188,6 +202,20 @@ namespace test return 0; } + public override int OnSubscriptionEvent(SubscriptionEvent e) + { + switch (e.getType()) + { + case tsip_subscribe_event_type_t.tsip_i_notify: + String ev = e.getSipMessage().getSipHeaderValue("Event"); + Console.WriteLine("Event=%s", ev); + break; + default: + break; + } + return base.OnSubscriptionEvent(e); + } + public override int OnPublicationEvent(PublicationEvent e) { short code = e.getCode(); diff --git a/trunk/tinyMEDIA/include/tinymedia/tmedia_qos.h b/trunk/tinyMEDIA/include/tinymedia/tmedia_qos.h index 4e36826a..5626c62c 100644 --- a/trunk/tinyMEDIA/include/tinymedia/tmedia_qos.h +++ b/trunk/tinyMEDIA/include/tinymedia/tmedia_qos.h @@ -101,6 +101,7 @@ tmedia_qos_tline_t; TINYMEDIA_API tmedia_qos_stype_t tmedia_qos_get_type(const tsdp_header_M_t* m); TINYMEDIA_API tmedia_qos_tline_t* tmedia_qos_tline_from_sdp(const tsdp_header_M_t* m); TINYMEDIA_API int tmedia_qos_tline_to_sdp(const tmedia_qos_tline_t* self, tsdp_header_M_t* m); +TINYMEDIA_API tsk_bool_t tmedia_qos_tline_canresume(const tmedia_qos_tline_t* self); /* QoS table-line for E2E type*/ typedef struct tmedia_qos_tline_e2e_s @@ -121,8 +122,8 @@ typedef struct tmedia_qos_tline_e2e_s } send; struct{ - tsk_bool_t current:1; - tsk_bool_t confirm:1; + unsigned current:1; + unsigned confirm:1; tmedia_qos_strength_t strength; } recv; } @@ -131,6 +132,8 @@ tmedia_qos_tline_e2e_t; TINYMEDIA_API tmedia_qos_tline_e2e_t* tmedia_qos_tline_e2e_create(tmedia_qos_strength_t strength); TINYMEDIA_API tmedia_qos_tline_e2e_t* tmedia_qos_tline_e2e_from_sdp(const tsdp_header_M_t* m); TINYMEDIA_API int tmedia_qos_tline_e2e_to_sdp(const tmedia_qos_tline_e2e_t* self, tsdp_header_M_t* m); +TINYMEDIA_API int tmedia_qos_tline_e2e_set_ro(tmedia_qos_tline_e2e_t* self, const tmedia_qos_tline_e2e_t* ro); +TINYMEDIA_API tsk_bool_t tmedia_qos_tline_e2e_canresume(const tmedia_qos_tline_e2e_t* self); /* QoS table-line for Segented type*/ typedef struct tmedia_qos_tline_segmented_s @@ -176,7 +179,8 @@ tmedia_qos_tline_segmented_t; TINYMEDIA_API tmedia_qos_tline_segmented_t* tmedia_qos_tline_segmented_create(tmedia_qos_strength_t strength); TINYMEDIA_API tmedia_qos_tline_segmented_t* tmedia_qos_tline_segmented_from_sdp(const tsdp_header_M_t* m); TINYMEDIA_API int tmedia_qos_tline_segmented_to_sdp(const tmedia_qos_tline_segmented_t* self, tsdp_header_M_t* m); - +TINYMEDIA_API int tmedia_qos_tline_segmented_set_ro(tmedia_qos_tline_segmented_t* self, const tmedia_qos_tline_segmented_t* ro); +TINYMEDIA_API tsk_bool_t tmedia_qos_tline_segmented_canresume(const tmedia_qos_tline_segmented_t* self); TINYMEDIA_GEXTERN const tsk_object_def_t *tmedia_qos_tline_segmented_def_t; TINYMEDIA_GEXTERN const tsk_object_def_t *tmedia_qos_tline_e2e_def_t; diff --git a/trunk/tinyMEDIA/include/tinymedia/tmedia_session.h b/trunk/tinyMEDIA/include/tinymedia/tmedia_session.h index ace26b71..3c8aeb79 100644 --- a/trunk/tinyMEDIA/include/tinymedia/tmedia_session.h +++ b/trunk/tinyMEDIA/include/tinymedia/tmedia_session.h @@ -45,6 +45,8 @@ TMEDIA_BEGIN_DECLS /**Max number of plugins (session types) we can create */ #define TMED_SESSION_MAX_PLUGINS 0x0F +#define TMEDIA_SESSION_SET(); + /** Base objct used for all media sessions */ typedef struct tmedia_session_s { @@ -84,6 +86,7 @@ typedef struct tmedia_session_plugin_def_s //! the media name. e.g. "audio", "video", "message", "image" etc. const char* media; + int (*configure) (tmedia_session_t* , const va_list *app); int (* prepare) (tmedia_session_t* ); int (* start) (tmedia_session_t* ); int (* pause) (tmedia_session_t* ); @@ -195,6 +198,7 @@ tmedia_session_mgr_t; TINYMEDIA_API tmedia_session_mgr_t* tmedia_session_mgr_create(tmedia_type_t type, const char* addr, tsk_bool_t ipv6); TINYMEDIA_API int tmedia_session_mgr_start(tmedia_session_mgr_t* self); +TINYMEDIA_API int tmedia_session_mgr_configure(tmedia_session_mgr_t* self, tmedia_type_t type, ...); TINYMEDIA_API int tmedia_session_mgr_stop(tmedia_session_mgr_t* self); TINYMEDIA_API const tsdp_message_t* tmedia_session_mgr_get_lo(tmedia_session_mgr_t* self); TINYMEDIA_API int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t* sdp); diff --git a/trunk/tinyMEDIA/src/tmedia_qos.c b/trunk/tinyMEDIA/src/tmedia_qos.c index b01a26a8..106919fd 100644 --- a/trunk/tinyMEDIA/src/tmedia_qos.c +++ b/trunk/tinyMEDIA/src/tmedia_qos.c @@ -112,6 +112,11 @@ tmedia_qos_stype_t tmedia_qos_get_type(const tsdp_header_M_t* m) tmedia_qos_tline_t* tmedia_qos_tline_from_sdp(const tsdp_header_M_t* m) { + if(!m){ + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + switch(tmedia_qos_get_type(m)){ case tmedia_qos_stype_e2e: return (tmedia_qos_tline_t*)tmedia_qos_tline_e2e_from_sdp(m); @@ -124,7 +129,12 @@ tmedia_qos_tline_t* tmedia_qos_tline_from_sdp(const tsdp_header_M_t* m) int tmedia_qos_tline_to_sdp(const tmedia_qos_tline_t* self, tsdp_header_M_t* m) { - switch(tmedia_qos_get_type(m)){ + if(!self || !m){ + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + switch(self->type){ case tmedia_qos_stype_e2e: return tmedia_qos_tline_e2e_to_sdp((tmedia_qos_tline_e2e_t*)self, m); case tmedia_qos_stype_segmented: @@ -134,6 +144,21 @@ int tmedia_qos_tline_to_sdp(const tmedia_qos_tline_t* self, tsdp_header_M_t* m) } } +tsk_bool_t tmedia_qos_tline_canresume(const tmedia_qos_tline_t* self) +{ + if(!self){ + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_true; + } + switch(self->type){ + case tmedia_qos_stype_segmented: + return tmedia_qos_tline_segmented_canresume((const tmedia_qos_tline_segmented_t*)self); + case tmedia_qos_stype_e2e: + return tmedia_qos_tline_e2e_canresume((const tmedia_qos_tline_e2e_t*)self); + default: + return tsk_true; + } +} /* ========================= E2E ==================================*/ @@ -266,8 +291,9 @@ int tmedia_qos_tline_e2e_to_sdp(const tmedia_qos_tline_e2e_t* self, tsdp_header_ a=des:qos mandatory e2e sendrecv */ + /* curr */ - tsk_sprintf(&temp, "qos e2e %s", self->recv.current ? "recv" : (self->send.current ? "send" : "none")); + tsk_sprintf(&temp, "qos e2e %s", (self->recv.current && self->send.current) ? "sendrecv" : (self->recv.current ? "recv" : (self->send.current ? "send" : "none"))); tsdp_header_M_add_headers(m, TSDP_HEADER_A_VA_ARGS("curr", temp), tsk_null); @@ -298,9 +324,84 @@ int tmedia_qos_tline_e2e_to_sdp(const tmedia_qos_tline_e2e_t* self, tsdp_header_ TSK_FREE(temp); } + /* conf (should not request confirm on "send" direction)*/ + if(self->recv.confirm){ + tsdp_header_M_add_headers(m, + TSDP_HEADER_A_VA_ARGS("conf", "qos e2e recv"), + tsk_null); + } return 0; } +int tmedia_qos_tline_e2e_set_ro(tmedia_qos_tline_e2e_t* self, const tmedia_qos_tline_e2e_t* ro) +{ + if(!self || !ro){ + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + /* We were the offerer + * Remote asked for confirmation in its "recv" direction? + * "recv" direction for remote is our "send" direction + * As we don't support RSVP (under the way), confirm immediatly. + * "send" direction should not requested for confirmation + */ + if(ro->recv.confirm){ + self->send.current = tsk_true; + goto bail; + } + if(ro->send.current){ + self->recv.confirm = tsk_false; /* remote confirmed */ + self->recv.current = tsk_true; /* because ro confirmed */ + self->send.current = tsk_true; /* beacuse we don't support RSVP */ + goto bail; + } + + /* We are the answerer + * As we don't support RSVP (under the way): + * ==> request confirmation for "recv" direction if equal to "none" (not reserved) + * => + */ + if(!self->recv.current){ + self->recv.confirm = tsk_true; + goto bail; + } + +bail: + /* all other cases: success */ + return 0; +} + +tsk_bool_t tmedia_qos_tline_e2e_canresume(const tmedia_qos_tline_e2e_t* self) +{ + if(!self){ + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_true; + } + + /* Example + a=curr:qos e2e none + a=des:qos mandatory e2e sendrecv + + Or + + a=curr:qos e2e send + a=des:qos mandatory e2e recv + a=des:qos optional e2e send + */ + + /* only "mandatory" strength should force the application to continue nego. */ + if(self->recv.strength == tmedia_qos_strength_mandatory && !self->recv.current){ + return tsk_false; + } + /*else */if(self->send.strength == tmedia_qos_strength_mandatory && !self->send.current){ + return tsk_false; + } + + /* "optinal" and "none" strengths */ + return tsk_true; +} + // // E2E QoS line object definition // @@ -548,14 +649,14 @@ int tmedia_qos_tline_segmented_to_sdp(const tmedia_qos_tline_segmented_t* self, */ /* curr:local */ - tsk_sprintf(&temp, "qos local %s", self->local_recv.current ? "recv" : (self->local_send.current ? "send" : "none")); + tsk_sprintf(&temp, "qos local %s", (self->local_recv.current && self->local_send.current) ? "sendrecv" : (self->local_recv.current ? "recv" : (self->local_send.current ? "send" : "none"))); tsdp_header_M_add_headers(m, TSDP_HEADER_A_VA_ARGS("curr", temp), tsk_null); TSK_FREE(temp); /* curr:remote */ - tsk_sprintf(&temp, "qos remote %s", self->remote_recv.current ? "recv" : (self->remote_send.current ? "send" : "none")); + tsk_sprintf(&temp, "qos remote %s", (self->remote_recv.current && self->remote_send.current) ? "sendrecv" : (self->remote_recv.current ? "recv" : (self->remote_send.current ? "send" : "none"))); tsdp_header_M_add_headers(m, TSDP_HEADER_A_VA_ARGS("curr", temp), tsk_null); @@ -613,9 +714,87 @@ int tmedia_qos_tline_segmented_to_sdp(const tmedia_qos_tline_segmented_t* self, TSK_FREE(temp); } + /* conf */ + if(self->remote_recv.confirm || self->remote_send.confirm){ + tsk_sprintf(&temp, "qos remote %s", (self->remote_recv.confirm && self->remote_send.confirm) ? "sendrecv" : (self->remote_recv.confirm ? "recv" : (self->remote_send.confirm ? "send" : "none"))); + tsdp_header_M_add_headers(m, + TSDP_HEADER_A_VA_ARGS("conf", temp), + tsk_null); + TSK_FREE(temp); + } + return 0; } +int tmedia_qos_tline_segmented_set_ro(tmedia_qos_tline_segmented_t* self, const tmedia_qos_tline_segmented_t* ro) +{ + if(!self || !ro){ + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + ////////////// + if(!ro->local_recv.current && !ro->remote_recv.confirm){ + /* request confirmation */ + self->remote_recv.confirm = tsk_true; + } + else{ + self->remote_recv.confirm = tsk_false; + self->local_recv.current = tsk_true; + } + if(!ro->local_send.current && !ro->remote_send.confirm){ + /* request confirmation */ + self->remote_send.confirm = tsk_true; + } + else{ + self->remote_send.confirm = tsk_false; + self->local_send.current = tsk_true; + } + + ////////////// + if(ro->remote_recv.confirm){ + self->local_recv.current = tsk_true; + } + if(ro->remote_send.confirm){ + self->local_send.current = tsk_true; + } + + ////////////// + if(ro->local_recv.current){ + self->remote_recv.current = tsk_true; + } + if(ro->local_send.current){ + self->remote_send.current = tsk_true; + } + + return 0; +} + +tsk_bool_t tmedia_qos_tline_segmented_canresume(const tmedia_qos_tline_segmented_t* self) +{ + if(!self){ + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_true; + } + + /* only "mandatory" strength should force the application to continue nego. */ + if(self->local_recv.strength == tmedia_qos_strength_mandatory && !self->local_recv.current){ + return tsk_false; + } + else if(self->local_send.strength == tmedia_qos_strength_mandatory && !self->local_send.current){ + return tsk_false; + } + else if(self->remote_recv.strength == tmedia_qos_strength_mandatory && !self->remote_recv.current){ + return tsk_false; + } + else if(self->remote_send.strength == tmedia_qos_strength_mandatory && !self->remote_send.current){ + return tsk_false; + } + + /* "optinal" and "none" strengths */ + return tsk_true; +} + // // Segmented QoS line object definition // diff --git a/trunk/tinyMEDIA/src/tmedia_session.c b/trunk/tinyMEDIA/src/tmedia_session.c index 8fec1a2d..29953ebf 100644 --- a/trunk/tinyMEDIA/src/tmedia_session.c +++ b/trunk/tinyMEDIA/src/tmedia_session.c @@ -480,6 +480,45 @@ int tmedia_session_mgr_start(tmedia_session_mgr_t* self) return 0; } +/**@ingroup tmedia_session_group +* Configures one or several sessions. +* @param self The session manager +* @param type The type of the sessions to configure +* @param ... Any TMEDIA_SESSION_SET_*() macros +* @retval Zero if succeed and non-zero error code otherwise +*/ +int tmedia_session_mgr_configure(tmedia_session_mgr_t* self, tmedia_type_t type, ...) +{ + tsk_list_item_t* item; + tmedia_session_t* session; + va_list ap; + + if(!self){ + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + tsk_list_foreach(item, self->sessions){ + if(!(session = item->data)){ + TSK_DEBUG_ERROR("Invalid session"); + return -2; + } + + /* does not support configure() */ + if(!session->plugin->configure){ + continue; + } + + va_start(ap, type); + if(((session->type & type) == session->type) && session->plugin->configure(session, &ap)){ + TSK_DEBUG_ERROR("Failed to configue (%s) session", session->plugin->media); + } + va_end(ap); + } + + return 0; +} + /**@ingroup tmedia_session_group * Stops the session manager by stopping all underlying sessions. * @param self The session manager to stop. diff --git a/trunk/tinyMEDIA/src/tmedia_session_dummy.c b/trunk/tinyMEDIA/src/tmedia_session_dummy.c index f75cd896..d927e095 100644 --- a/trunk/tinyMEDIA/src/tmedia_session_dummy.c +++ b/trunk/tinyMEDIA/src/tmedia_session_dummy.c @@ -34,6 +34,17 @@ /* ============ Audio Session ================= */ +int tmedia_session_daudio_configure(tmedia_session_t* self, const va_list *app) +{ + tmedia_session_daudio_t* daudio; + + TSK_DEBUG_INFO("tmedia_session_daudio_prepare"); + + daudio = (tmedia_session_daudio_t*)self; + + return 0; +} + int tmedia_session_daudio_prepare(tmedia_session_t* self) { tmedia_session_daudio_t* daudio; @@ -139,6 +150,17 @@ int tmedia_session_daudio_set_ro(tmedia_session_t* self, const tsdp_header_M_t* /* ============ Video Session ================= */ +int tmedia_session_dvideo_configure(tmedia_session_t* self, const va_list *app) +{ + tmedia_session_dvideo_t* dvideo; + + TSK_DEBUG_INFO("tmedia_session_dvideo_configure"); + + dvideo = (tmedia_session_dvideo_t*)self; + + return 0; +} + int tmedia_session_dvideo_prepare(tmedia_session_t* self) { tmedia_session_dvideo_t* dvideo; @@ -244,6 +266,17 @@ int tmedia_session_dvideo_set_ro(tmedia_session_t* self, const tsdp_header_M_t* /* ============ Msrp Session ================= */ +int tmedia_session_dmsrp_configure(tmedia_session_t* self, const va_list *app) +{ + tmedia_session_dmsrp_t* dmsrp; + + TSK_DEBUG_INFO("tmedia_session_dmsrp_configure"); + + dmsrp = (tmedia_session_dmsrp_t*)self; + + return 0; +} + int tmedia_session_dmsrp_prepare(tmedia_session_t* self) { TSK_DEBUG_INFO("tmedia_session_dmsrp_prepare"); @@ -326,6 +359,7 @@ static const tmedia_session_plugin_def_t tmedia_session_daudio_plugin_def_s = tmedia_audio, "audio", + tmedia_session_daudio_configure, tmedia_session_daudio_prepare, tmedia_session_daudio_start, tmedia_session_daudio_stop, @@ -378,6 +412,7 @@ static const tmedia_session_plugin_def_t tmedia_session_dvideo_plugin_def_s = tmedia_video, "video", + tmedia_session_dvideo_configure, tmedia_session_dvideo_prepare, tmedia_session_dvideo_start, tmedia_session_dvideo_stop, @@ -430,6 +465,7 @@ static const tmedia_session_plugin_def_t tmedia_session_dmsrp_plugin_def_s = tmedia_msrp, "message", + tmedia_session_dmsrp_configure, tmedia_session_dmsrp_prepare, tmedia_session_dmsrp_start, tmedia_session_dmsrp_stop, diff --git a/trunk/tinyMEDIA/src/tmedia_session_ghost.c b/trunk/tinyMEDIA/src/tmedia_session_ghost.c index 8c668e2d..41e91268 100644 --- a/trunk/tinyMEDIA/src/tmedia_session_ghost.c +++ b/trunk/tinyMEDIA/src/tmedia_session_ghost.c @@ -132,6 +132,7 @@ static const tmedia_session_plugin_def_t tmedia_session_ghost_plugin_def_s = tmedia_ghost, "ghost", + tsk_null, tmedia_session_ghost_prepare, tmedia_session_ghost_start, tmedia_session_ghost_stop, diff --git a/trunk/tinyMEDIA/test/test_qos.h b/trunk/tinyMEDIA/test/test_qos.h index 0559627b..c91b2947 100644 --- a/trunk/tinyMEDIA/test/test_qos.h +++ b/trunk/tinyMEDIA/test/test_qos.h @@ -22,13 +22,33 @@ #ifndef _TEST_QOS_H_ #define _TEST_QOS_H_ -void test_qos() +char* test_qos_tostring(const tmedia_qos_tline_t* tline) +{ + char* ret = tsk_null; + tsdp_header_M_t* M; + + if(!tline){ + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + M = tsdp_header_M_create("audio", 20000, "RTP/AVP"); + tmedia_qos_tline_to_sdp(tline, M); + + ret = tsdp_header_tostring(TSDP_HEADER(M)); + TSK_OBJECT_SAFE_FREE(M); + + return ret; +} + +void test_qos_parser() { tsdp_header_M_t* M; tmedia_qos_tline_e2e_t* e2e; tmedia_qos_tline_segmented_t* segmented; char* temp = tsk_null; tmedia_qos_stype_t type; + tsk_bool_t canresume; /* test E2E */ M = tsdp_header_M_create("audio", 20000, "RTP/AVP"); @@ -45,6 +65,7 @@ void test_qos() // from_sdp TSK_OBJECT_SAFE_FREE(e2e); e2e = tmedia_qos_tline_e2e_from_sdp(M); + canresume = tmedia_qos_tline_e2e_canresume(e2e); tmedia_qos_tline_e2e_to_sdp(e2e, M); if((temp = tsdp_header_tostring(TSDP_HEADER(M)))){ TSK_DEBUG_INFO("e2e from_sdp: %s", temp); @@ -71,6 +92,7 @@ void test_qos() // from_sdp TSK_OBJECT_SAFE_FREE(segmented); segmented = tmedia_qos_tline_segmented_from_sdp(M); + canresume = tmedia_qos_tline_segmented_canresume(segmented); tmedia_qos_tline_segmented_to_sdp(segmented, M); if((temp = tsdp_header_tostring(TSDP_HEADER(M)))){ TSK_DEBUG_INFO("Segmented from_sdp: %s", temp); @@ -83,4 +105,163 @@ void test_qos() TSK_OBJECT_SAFE_FREE(M); } + +void test_qos_e2e_neg() +{ + tmedia_qos_tline_e2e_t *e2eA = tsk_null, *e2eB = tsk_null; + char* temp = tsk_null; + + /* SDP1: A includes end-to-end quality of service preconditions in the + initial offer. + + m=audio 20000 RTP/AVP 0 + c=IN IP4 192.0.2.1 + a=curr:qos e2e none + a=des:qos mandatory e2e sendrecv + */ + e2eA = tmedia_qos_tline_e2e_create(tmedia_qos_strength_mandatory); + if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eA))){ + TSK_DEBUG_INFO("SDP1=\n%s", temp); + TSK_FREE(temp); + } + + /* SDP2: Since B uses RSVP, it can know when resources in its "send" + direction are available, because it will receive RESV messages from + the network. However, it does not know the status of the + reservations in the other direction. B requests confirmation for + resource reservations in its "recv" direction to the peer user agent + A in its answer. + + m=audio 30000 RTP/AVP 0 + c=IN IP4 192.0.2.4 + a=curr:qos e2e none + a=des:qos mandatory e2e sendrecv + a=conf:qos e2e recv + */ + e2eB = tmedia_qos_tline_e2e_create(tmedia_qos_strength_mandatory); + tmedia_qos_tline_e2e_set_ro(e2eB, e2eA); + if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eB))){ + TSK_DEBUG_INFO("SDP2=\n%s", temp); + TSK_FREE(temp); + } + + /* SDP3: When A receives RESV messages, it sends an updated offer (5) to B: + + m=audio 20000 RTP/AVP 0 + c=IN IP4 192.0.2.1 + a=curr:qos e2e send + a=des:qos mandatory e2e sendrecv + */ + tmedia_qos_tline_e2e_set_ro(e2eA, e2eB); + if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eA))){ + TSK_DEBUG_INFO("SDP3=\n%s", temp); + TSK_FREE(temp); + } + + /* SDP4: B responds with an answer (6) which contains the current status + of the resource reservation (i.e., sendrecv): + + m=audio 30000 RTP/AVP 0 + c=IN IP4 192.0.2.4 + a=curr:qos e2e sendrecv + a=des:qos mandatory e2e sendrecv + */ + tmedia_qos_tline_e2e_set_ro(e2eB, e2eA); + if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eB))){ + TSK_DEBUG_INFO("SDP4=\n%s", temp); + TSK_FREE(temp); + } + + /* A receive B's response */ + tmedia_qos_tline_e2e_set_ro(e2eA, e2eB); + if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eA))){ + TSK_DEBUG_INFO("SDP5=\n%s", temp); + TSK_FREE(temp); + } + + if(tmedia_qos_tline_e2e_canresume(e2eA)){ + TSK_DEBUG_INFO("A can resume"); + } + else{ + TSK_DEBUG_ERROR("A can't resume"); + } + + if(tmedia_qos_tline_e2e_canresume(e2eB)){ + TSK_DEBUG_INFO("B can resume"); + } + else{ + TSK_DEBUG_ERROR("B can't resume"); + } + + TSK_OBJECT_SAFE_FREE(e2eB); + TSK_OBJECT_SAFE_FREE(e2eA); +} + + +void test_qos_segmented_neg() +{ + tmedia_qos_tline_segmented_t *segA = tsk_null, *segB = tsk_null; + char* temp = tsk_null; + + /* INVITE + a=curr:qos local none + a=curr:qos remote none + a=des:qos mandatory local sendrecv + a=des:qos mandatory remote sendrecv + */ + segA = tmedia_qos_tline_segmented_create(tmedia_qos_strength_mandatory); + if((temp = test_qos_tostring((const tmedia_qos_tline_t*)segA))){ + TSK_DEBUG_INFO("INVITE=\n%s", temp); + TSK_FREE(temp); + } + + /* 183 Sesson progress + a=curr:qos local none + a=curr:qos remote none + a=des:qos mandatory local sendrecv + a=des:qos mandatory remote sendrecv + a=conf:qos remote sendrecv + */ + segB = tmedia_qos_tline_segmented_create(tmedia_qos_strength_mandatory); + tmedia_qos_tline_segmented_set_ro(segB, segA); + if((temp = test_qos_tostring((const tmedia_qos_tline_t*)segB))){ + TSK_DEBUG_INFO("183=\n%s", temp); + TSK_FREE(temp); + } + + /* UPDATE + a=curr:qos local sendrecv + a=curr:qos remote none + a=des:qos mandatory local sendrecv + a=des:qos mandatory remote sendrecv + */ + tmedia_qos_tline_segmented_set_ro(segA, segB); + if((temp = test_qos_tostring((const tmedia_qos_tline_t*)segA))){ + TSK_DEBUG_INFO("UPDATE=\n%s", temp); + TSK_FREE(temp); + } + + /* 200 OK + a=curr:qos local sendrecv + a=curr:qos remote sendrecv + a=des:qos mandatory local sendrecv + a=des:qos mandatory remote sendrecv + */ + tmedia_qos_tline_segmented_set_ro(segB, segA); + if((temp = test_qos_tostring((const tmedia_qos_tline_t*)segB))){ + TSK_DEBUG_INFO("200OK=\n%s", temp); + TSK_FREE(temp); + } + + TSK_OBJECT_SAFE_FREE(segA); + TSK_OBJECT_SAFE_FREE(segB); +} + +void test_qos() +{ + //test_qos_parser(); + //test_qos_e2e_neg(); + test_qos_segmented_neg(); +} + #endif /* _TEST_QOS_H_ */ diff --git a/trunk/tinySIP/include/tinysip/tsip_ssession.h b/trunk/tinySIP/include/tinysip/tsip_ssession.h index a80bd1ac..1f1ed89d 100644 --- a/trunk/tinySIP/include/tinysip/tsip_ssession.h +++ b/trunk/tinySIP/include/tinysip/tsip_ssession.h @@ -67,7 +67,8 @@ typedef enum tsip_ssession_param_type_e sstype_from, sstype_nocontact, sstype_expires, - sstype_silent_hangup + sstype_silent_hangup, + sstype_media } tsip_ssession_param_type_t; @@ -81,8 +82,27 @@ tsip_ssession_param_type_t; #define TSIP_SSESSION_SET_NO_CONTACT(ENABLED_BOOL) sstype_nocontact, (tsk_bool_t)ENABLED_BOOL #define TSIP_SSESSION_SET_EXPIRES(VALUE_UINT) sstype_expires, (unsigned)VALUE_UINT #define TSIP_SSESSION_SET_SILENT_HANGUP(ENABLED_BOOL) sstype_silent_hangup, (tsk_bool_t)ENABLED_BOOL +#define TSIP_SSESSION_SET_MEDIA(...) sstype_media, ##__VA_ARGS__ #define TSIP_SSESSION_SET_NULL() sstype_null +typedef enum tsip_msession_param_type_e +{ + mstype_null = tsk_null, + + mstype_set_qos, + mstype_unset_qos, + mstype_set_timers, + mstype_unset_timers, +} +tsip_msession_param_type_t; + +#define TSIP_MSESSION_SET_QOS() +#define TSIP_MSESSION_UNSET_QOS() +#define TSIP_MSESSION_SET_TIMERS() +#define TSIP_MSESSION_UNSET_TIMERS() mstype_null + +#define TSIP_MSESSION_SET_NULL() + typedef struct tsip_ssession_s { TSK_DECLARE_OBJECT; diff --git a/trunk/tinySIP/include/tinysip_config.h b/trunk/tinySIP/include/tinysip_config.h index 5d2405e3..afc0fb98 100644 --- a/trunk/tinySIP/include/tinysip_config.h +++ b/trunk/tinySIP/include/tinysip_config.h @@ -64,7 +64,7 @@ #endif /* Whether to use SIP Compact headers */ -#define TSIP_COMPACT_HEADERS 1 +#define TSIP_COMPACT_HEADERS 0 #include #ifdef __SYMBIAN32__ diff --git a/trunk/tinySIP/test/test_sipmessages.h b/trunk/tinySIP/test/test_sipmessages.h index db065e7b..8e663a4e 100644 --- a/trunk/tinySIP/test/test_sipmessages.h +++ b/trunk/tinySIP/test/test_sipmessages.h @@ -58,6 +58,7 @@ "Content-Length: 0\r\n" \ "Call-ID: 1261611941121\r\n" \ "Min-Expires: 30\r\n" \ + "Event: reg\r\n" \ "From: ;tag=1261611941121\r\n" \ "Contact: ;mobility=fixed;+deviceid=\"DD1289FA-C3D7-47bd-A40D-F1F1B2CC5FFC\";expires=300,;mobility=fixed;+deviceid=\"DD1289FA-C3D7-47bd-A40D-F1F1B2CC5FFC\";expires=300,;mobility=fixed;+deviceid=\"DD1289FA-C3D7-47bd-A40D-F1F1B2CC5FFC\";expires=300\r\n"\ "Contact: ;expires=3600;q=1.0,;expires=3600;q=1.0\r\n" \ diff --git a/trunk/tinyXCAP/include/tinyxcap/txcap_action.h b/trunk/tinyXCAP/include/tinyxcap/txcap_action.h index 5d3a1699..36b9f669 100644 --- a/trunk/tinyXCAP/include/tinyxcap/txcap_action.h +++ b/trunk/tinyXCAP/include/tinyxcap/txcap_action.h @@ -200,7 +200,7 @@ int ret = txcap_action_create_element(stack, #define TXCAP_ACTION_SET_OPTION(ID_INT, VALUE_STR) txcap_apt_option, (thttp_action_option_t)ID_INT, (const char*)VALUE_STR #define TXCAP_ACTION_SET_HEADER(NAME_STR, VALUE_STR) txcap_apt_header, (const char*)NAME_STR, (const char*)VALUE_STR #define TXCAP_ACTION_SET_PAYLOAD(PAY_PTR, PAY_SIZE) txcap_apt_payload, (const void*)PAY_PTR, (size_t)PAY_SIZE -#define TXCAP_ACTION_SET_SELECTOR(AUID_STR, ...) txcap_apt_selector, (const char*)AUID_STR, __VA_ARGS__ +#define TXCAP_ACTION_SET_SELECTOR(AUID_STR, ...) txcap_apt_selector, (const char*)AUID_STR, ##__VA_ARGS__ #define TXCAP_ACTION_SET_REQUEST_URI(URI_STR) txcap_apt_urlstring, (const char*)URI_STR #define TXCAP_ACTION_SET_NULL() txcap_apt_null diff --git a/trunk/vs_2005/tinyDEMO/tinyDEMO.sln b/trunk/vs_2005/tinyDEMO/tinyDEMO.sln index 3ffaf094..6b78b891 100644 --- a/trunk/vs_2005/tinyDEMO/tinyDEMO.sln +++ b/trunk/vs_2005/tinyDEMO/tinyDEMO.sln @@ -21,6 +21,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinySDP", "..\tinySDP\tinyS EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinySMS", "..\tinySMS\tinySMS.vcproj", "{9A3A5AF3-2333-4477-B880-7F901F9D8972}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyDAV", "..\tinyDAV\tinyDAV.vcproj", "{8E2F0B2E-2596-4010-BF4A-2F688975B5C1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyRTP", "..\tinyRTP\tinyRTP.vcproj", "{99B7D02F-8C70-4B45-AF3C-92313C3CEE15}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -105,6 +109,18 @@ Global {9A3A5AF3-2333-4477-B880-7F901F9D8972}.Release|Win32.ActiveCfg = Release|Win32 {9A3A5AF3-2333-4477-B880-7F901F9D8972}.Release|Win32.Build.0 = Release|Win32 {9A3A5AF3-2333-4477-B880-7F901F9D8972}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Win32 + {8E2F0B2E-2596-4010-BF4A-2F688975B5C1}.Debug|Win32.ActiveCfg = Debug|Win32 + {8E2F0B2E-2596-4010-BF4A-2F688975B5C1}.Debug|Win32.Build.0 = Debug|Win32 + {8E2F0B2E-2596-4010-BF4A-2F688975B5C1}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Win32 + {8E2F0B2E-2596-4010-BF4A-2F688975B5C1}.Release|Win32.ActiveCfg = Release|Win32 + {8E2F0B2E-2596-4010-BF4A-2F688975B5C1}.Release|Win32.Build.0 = Release|Win32 + {8E2F0B2E-2596-4010-BF4A-2F688975B5C1}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Win32 + {99B7D02F-8C70-4B45-AF3C-92313C3CEE15}.Debug|Win32.ActiveCfg = Debug|Win32 + {99B7D02F-8C70-4B45-AF3C-92313C3CEE15}.Debug|Win32.Build.0 = Debug|Win32 + {99B7D02F-8C70-4B45-AF3C-92313C3CEE15}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Win32 + {99B7D02F-8C70-4B45-AF3C-92313C3CEE15}.Release|Win32.ActiveCfg = Release|Win32 + {99B7D02F-8C70-4B45-AF3C-92313C3CEE15}.Release|Win32.Build.0 = Release|Win32 + {99B7D02F-8C70-4B45-AF3C-92313C3CEE15}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/trunk/vs_2005/tinyDEMO/tinyDEMO.vcproj b/trunk/vs_2005/tinyDEMO/tinyDEMO.vcproj index 6acfae23..a6774fb6 100644 --- a/trunk/vs_2005/tinyDEMO/tinyDEMO.vcproj +++ b/trunk/vs_2005/tinyDEMO/tinyDEMO.vcproj @@ -40,7 +40,7 @@ + +