summaryrefslogtreecommitdiffstats
path: root/branches/1.0/tinySIP/src/dialogs
diff options
context:
space:
mode:
Diffstat (limited to 'branches/1.0/tinySIP/src/dialogs')
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog.c1171
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.c1359
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.cdiv.c0
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.client.c271
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.conf.c1
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.ect.c126
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.hold.c247
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.qos.c92
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.server.c718
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.timers.c309
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_layer.c500
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_message.c546
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_options.c501
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_publish.client.c716
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.c505
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.client.c430
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.server.c199
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_subscribe.client.c754
-rw-r--r--branches/1.0/tinySIP/src/dialogs/tsip_dialog_subscribe.server.c1
19 files changed, 0 insertions, 8446 deletions
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog.c
deleted file mode 100644
index ea4f436..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog.c
+++ /dev/null
@@ -1,1171 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog.c
- * @brief SIP dialog base class as per RFC 3261 subclause 17.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog.h"
-
-#include "tinysip/dialogs/tsip_dialog_layer.h"
-#include "tinysip/transactions/tsip_transac_layer.h"
-
-#include "tinysip/transactions/tsip_transac_nict.h"
-
-#include "tinysip/parsers/tsip_parser_uri.h"
-
-#include "tinysip/headers/tsip_header_Authorization.h"
-#include "tinysip/headers/tsip_header_Contact.h"
-#include "tinysip/headers/tsip_header_Dummy.h"
-#include "tinysip/headers/tsip_header_Expires.h"
-#include "tinysip/headers/tsip_header_P_Preferred_Identity.h"
-#include "tinysip/headers/tsip_header_Proxy_Authenticate.h"
-#include "tinysip/headers/tsip_header_Proxy_Authorization.h"
-#include "tinysip/headers/tsip_header_Record_Route.h"
-#include "tinysip/headers/tsip_header_Route.h"
-#include "tinysip/headers/tsip_header_Subscription_State.h"
-#include "tinysip/headers/tsip_header_WWW_Authenticate.h"
-
-#include "tsk_debug.h"
-#include "tsk_time.h"
-
-int tsip_dialog_update_challenges(tsip_dialog_t *self, const tsip_response_t* response, tsk_bool_t acceptNewVector);
-int tsip_dialog_add_common_headers(const tsip_dialog_t *self, tsip_request_t* request);
-
-extern tsip_uri_t* tsip_stack_get_pcscf_uri(const tsip_stack_t *self, tsk_bool_t lr);
-extern tsip_uri_t* tsip_stack_get_contacturi(const tsip_stack_t *self, const char* protocol);
-
-tsip_request_t *tsip_dialog_request_new(const tsip_dialog_t *self, const char* method)
-{
- tsip_request_t *request = tsk_null;
- tsip_uri_t *to_uri, *from_uri, *request_uri;
- const char *call_id;
- int copy_routes_start = -1; /* NONE */
- const tsk_list_item_t* item;
-
- /*
- RFC 3261 - 12.2.1.1 Generating the Request
-
- The Call-ID of the request MUST be set to the Call-ID of the dialog.
- */
- call_id = self->callid;
-
- /*
- RFC 3261 - 12.2.1.1 Generating the Request
-
- Requests within a dialog MUST contain strictly monotonically
- increasing and contiguous CSeq sequence numbers (increasing-by-one)
- in each direction (excepting ACK and CANCEL of course, whose numbers
- equal the requests being acknowledged or cancelled). Therefore, if
- the local sequence number is not empty, the value of the local
- sequence number MUST be incremented by one, and this value MUST be
- placed into the CSeq header field.
- */
- /*if(!tsk_striequals(method, "ACK") && !tsk_striequals(method, "CANCEL"))
- {
- TSIP_DIALOG(self)->cseq_value +=1;
- }
- ===> See send method (cseq will be incremented before sending the request)
- */
-
-
- /*
- RFC 3261 - 12.2.1.1 Generating the Request
-
- The URI in the To field of the request MUST be set to the remote URI
- from the dialog state. The tag in the To header field of the request
- MUST be set to the remote tag of the dialog ID. The From URI of the
- request MUST be set to the local URI from the dialog state. The tag
- in the From header field of the request MUST be set to the local tag
- of the dialog ID. If the value of the remote or local tags is null,
- the tag parameter MUST be omitted from the To or From header fields,
- respectively.
- */
- to_uri = tsk_object_ref((void*)self->uri_remote);
- from_uri = tsk_object_ref((void*)self->uri_local);
-
-
- /*
- RFC 3261 - 12.2.1.1 Generating the Request
-
- If the route set is empty, the UAC MUST place the remote target URI
- into the Request-URI. The UAC MUST NOT add a Route header field to
- the request.
- */
- if(!self->record_routes || TSK_LIST_IS_EMPTY(self->record_routes)){
- request_uri = tsk_object_ref((void*)self->uri_remote_target);
- }
-
- /*
- RFC 3261 - 12.2.1.1 Generating the Request
-
- If the route set is not empty, and the first URI in the route set
- contains the lr parameter (see Section 19.1.1), the UAC MUST place
- the remote target URI into the Request-URI and MUST include a Route
- header field containing the route set values in order, including all
- parameters.
-
- If the route set is not empty, and its first URI does not contain the
- lr parameter, the UAC MUST place the first URI from the route set
- into the Request-URI, stripping any parameters that are not allowed
- in a Request-URI. The UAC MUST add a Route header field containing
- the remainder of the route set values in order, including all
- parameters. The UAC MUST then place the remote target URI into the
- Route header field as the last value.
-
- For example, if the remote target is sip:user@remoteua and the route
- set contains:
-
- <sip:proxy1>,<sip:proxy2>,<sip:proxy3;lr>,<sip:proxy4>
- */
- else{
- const tsip_uri_t *first_route = ((tsip_header_Record_Route_t*)TSK_LIST_FIRST_DATA(self->record_routes))->uri;
- if(tsk_params_have_param(first_route->params, "lr")){
- request_uri = tsk_object_ref(self->uri_remote_target);
- copy_routes_start = 0; /* Copy all */
- }
- else{
- request_uri = tsk_object_ref((void*)first_route);
- copy_routes_start = 1; /* Copy starting at index 1. */
- }
- }
-
- /*=====================================================================
- */
- request = tsip_request_new(method, request_uri, from_uri, to_uri, call_id, self->cseq_value);
- request->To->tag = tsk_strdup(self->tag_remote);
- request->From->tag = tsk_strdup(self->tag_local);
- request->update = tsk_true; /* Now signal that the message should be updated by the transport layer (Contact, SigComp, IPSec, ...) */
-
-
- /*
- RFC 3261 - 12.2.1.1 Generating the Request
-
- A UAC SHOULD include a Contact header field in any target refresh
- requests within a dialog, and unless there is a need to change it,
- the URI SHOULD be the same as used in previous requests within the
- dialog. If the "secure" flag is true, that URI MUST be a SIPS URI.
- As discussed in Section 12.2.2, a Contact header field in a target
- refresh request updates the remote target URI. This allows a UA to
- provide a new contact address, should its address change during the
- duration of the dialog.
- */
- switch(request->line.request.request_type){
- case tsip_MESSAGE:
- case tsip_PUBLISH:
- case tsip_BYE:
- {
- if(request->line.request.request_type == tsip_PUBLISH) {
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_EXPIRES_VA_ARGS(TSK_TIME_MS_2_S(self->expires)));
- }
- /* add caps in Accept-Contact headers */
- tsk_list_foreach(item, self->ss->caps) {
- const tsk_param_t* param = TSK_PARAM(item->data);
- char* value = tsk_null;
- tsk_sprintf(&value, "*;%s%s%s",
- param->name,
- param->value ? "=" : "",
- param->value ? param->value : "");
- if(value) {
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_DUMMY_VA_ARGS("Accept-Contact", value));
- TSK_FREE(value);
- }
- }
- break;
- }
-
- default:
- {
- char* contact = tsk_false;
- tsip_header_Contacts_L_t *hdr_contacts;
-
- if(request->line.request.request_type == tsip_OPTIONS ||
- request->line.request.request_type == tsip_PUBLISH ||
- request->line.request.request_type == tsip_REGISTER){
- /**** with expires */
- tsk_sprintf(&contact, "m: <%s:%s@%s:%d>;expires=%d\r\n", "sip", from_uri->user_name, "127.0.0.1", 5060, TSK_TIME_MS_2_S(self->expires));
- }
- else{
- /**** without expires */
- if(request->line.request.request_type == tsip_SUBSCRIBE){
- /* RFC 3265 - 3.1.1. Subscription Duration
- An "expires" parameter on the "Contact" header has no semantics for SUBSCRIBE and is explicitly
- not equivalent to an "Expires" header in a SUBSCRIBE request or response.
- */
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_EXPIRES_VA_ARGS(TSK_TIME_MS_2_S(self->expires)));
- }
- tsk_sprintf(&contact, "m: <%s:%s@%s:%d>\r\n", "sip", from_uri->user_name, "127.0.0.1", 5060);
- }
- hdr_contacts = tsip_header_Contact_parse(contact, tsk_strlen(contact));
- if(!TSK_LIST_IS_EMPTY(hdr_contacts)){
- request->Contact = tsk_object_ref(hdr_contacts->head->data);
- }
- TSK_OBJECT_SAFE_FREE(hdr_contacts);
- TSK_FREE(contact);
-
- /* Add capabilities as per RFC 3840 */
- if(request->Contact) {
- tsk_list_foreach(item, self->ss->caps){
- tsk_params_add_param(&TSIP_HEADER(request->Contact)->params, TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value);
- }
- }
-
- break;
- }
- }
-
- /* Update authorizations */
- if(self->state == tsip_initial && TSK_LIST_IS_EMPTY(self->challenges)){
- /* 3GPP TS 33.978 6.2.3.1 Procedures at the UE
- On sending a REGISTER request in order to indicate support for early IMS security procedures, the UE shall not
- include an Authorization header field and not include header fields or header field values as required by RFC3329.
- */
- if(TSIP_REQUEST_IS_REGISTER(request) && !TSIP_DIALOG_GET_STACK(self)->security.earlyIMS){
- /* 3GPP TS 24.229 - 5.1.1.2.2 Initial registration using IMS AKA
- On sending a REGISTER request, the UE shall populate the header fields as follows:
- a) an Authorization header field, with:
- - the "username" header field parameter, set to the value of the private user identity;
- - the "realm" header field parameter, set to the domain name of the home network;
- - the "uri" header field parameter, set to the SIP URI of the domain name of the home network;
- - the "nonce" header field parameter, set to an empty value; and
- - the "response" header field parameter, set to an empty value;
- */
- const char* realm = TSIP_DIALOG_GET_STACK(self)->network.realm ? TSIP_DIALOG_GET_STACK(self)->network.realm->host : "(null)";
- char* request_uri = tsip_uri_tostring(request->line.request.uri, tsk_false, tsk_false);
- tsip_header_t* auth_hdr = tsip_challenge_create_empty_header_authorization(TSIP_DIALOG_GET_STACK(self)->identity.impi, realm, request_uri);
- tsip_message_add_header(request, auth_hdr);
- tsk_object_unref(auth_hdr), auth_hdr = tsk_null;
- TSK_FREE(request_uri);
- }
- }
- else if(!TSK_LIST_IS_EMPTY(self->challenges)){
- tsip_challenge_t *challenge;
- tsip_header_t* auth_hdr;
- tsk_list_foreach(item, self->challenges){
- challenge = item->data;
- auth_hdr = tsip_challenge_create_header_authorization(challenge, request);
- if(auth_hdr){
- tsip_message_add_header(request, auth_hdr);
- tsk_object_unref(auth_hdr), auth_hdr = tsk_null;
- }
- }
- }
-
- /* Update CSeq */
- /* RFC 3261 - 13.2.2.4 2xx Responses
- Generating ACK: The sequence number of the CSeq header field MUST be
- the same as the INVITE being acknowledged, but the CSeq method MUST
- be ACK. The ACK MUST contain the same credentials as the INVITE. If
- the 2xx contains an offer (based on the rules above), the ACK MUST
- carry an answer in its body.
- ==> CSeq number will be added/updated by the caller of this function,
- credentials were added above.
- */
- if(!TSIP_REQUEST_IS_ACK(request) && !TSIP_REQUEST_IS_CANCEL(request)){
- request->CSeq->seq = ++(TSIP_DIALOG(self)->cseq_value);
- }
-
- /* Route generation
- * ==> http://betelco.blogspot.com/2008/11/proxy-and-service-route-discovery-in.html
- * The dialog Routes have been copied above.
-
- 3GPP TS 24.229 - 5.1.2A.1 UE-originating case
-
- The UE shall build a proper preloaded Route header field value for all new dialogs and standalone transactions. The UE
- shall build a list of Route header field values made out of the following, in this order:
- a) the P-CSCF URI containing the IP address or the FQDN learnt through the P-CSCF discovery procedures; and
- b) the P-CSCF port based on the security mechanism in use:
-
- - if IMS AKA or SIP digest with TLS is in use as a security mechanism, the protected server port learnt during
- the registration procedure;
- - if SIP digest without TLS, NASS-IMS bundled authentciation or GPRS-IMS-Bundled authentication is in
- use as a security mechanism, the unprotected server port used during the registration procedure;
- c) and the values received in the Service-Route header field saved from the 200 (OK) response to the last
- registration or re-registration of the public user identity with associated contact address.
- */
- if(!TSIP_REQUEST_IS_REGISTER(request))
- { // According to the above link ==> Initial/Re/De registration do not have routes.
- if(copy_routes_start != -1)
- { /* The dialog already have routes ==> copy them. */
- if(self->state == tsip_early || self->state == tsip_established){
- int32_t index = -1;
- tsk_list_foreach(item, self->record_routes){
- tsip_header_Record_Route_t *record_Route = ((tsip_header_Record_Route_t*)item->data);
- const tsip_uri_t* uri = record_Route->uri;
- tsip_header_Route_t *route = tsk_null;
- if(++index < copy_routes_start || !uri){
- continue;
- }
-
- if((route = tsip_header_Route_create(uri))){
- // copy parameters: see http://code.google.com/p/imsdroid/issues/detail?id=52
- if(!TSK_LIST_IS_EMPTY(TSIP_HEADER_PARAMS(record_Route))){
- if(!TSIP_HEADER_PARAMS(route)){
- TSIP_HEADER_PARAMS(route) = tsk_list_create();
- }
- tsk_list_pushback_list(TSIP_HEADER_PARAMS(route), TSIP_HEADER_PARAMS(record_Route));
- }
-
- tsip_message_add_header(request, TSIP_HEADER(route));
- TSK_OBJECT_SAFE_FREE(route);
- }
- }
- }
- }
- else
- { /* No routes associated to this dialog. */
- if(self->state == tsip_initial || self->state == tsip_early){
- /* GPP TS 24.229 section 5.1.2A [Generic procedures applicable to all methods excluding the REGISTER method]:
- The UE shall build a proper preloaded Route header field value for all new dialogs and standalone transactions. The UE
- shall build a list of Route header field values made out of the following, in this order:
- a) the P-CSCF URI containing the IP address or the FQDN learnt through the P-CSCF discovery procedures; and
- b) the P-CSCF port based on the security mechanism in use:
- - if IMS AKA or SIP digest with TLS is in use as a security mechanism, the protected server port learnt during
- the registration procedure;
- - if SIP digest without TLS, NASS-IMS bundled authentciation or GPRS-IMS-Bundled authentication is in
- use as a security mechanism, the unprotected server port used during the registration procedure;
- c) and the values received in the Service-Route header field saved from the 200 (OK) response to the last
- registration or re-registration of the public user identity with associated contact address.
- */
-#if _DEBUG && defined(SDS_HACK)/* FIXME: remove this */
- /* Ericsson SDS hack (INVITE with Proxy-CSCF as First route fail) */
-#else
- tsip_uri_t *uri = tsip_stack_get_pcscf_uri(TSIP_DIALOG_GET_STACK(self), tsk_true);
- // Proxy-CSCF as first route
- if(uri){
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_ROUTE_VA_ARGS(uri));
- TSK_OBJECT_SAFE_FREE(uri);
- }
-#endif
- // Service routes
- tsk_list_foreach(item, TSIP_DIALOG_GET_STACK(self)->service_routes){
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_ROUTE_VA_ARGS(item->data));
- }
- }
- }
- }
-
- /* Add headers associated to the dialog's session */
- tsk_list_foreach(item, self->ss->headers){
- if(!TSK_PARAM(item->data)->tag){
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_DUMMY_VA_ARGS(TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value));
- }
- }
-
- /* Add headers associated to the dialog's stack */
- tsk_list_foreach(item, self->ss->stack->headers){
- if(!TSK_PARAM(item->data)->tag){
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_DUMMY_VA_ARGS(TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value));
- }
- }
-
- /* Add common headers */
- tsip_dialog_add_common_headers(self, request);
-
- /* SigComp */
- if(self->ss->sigcomp_id){
- /* should be added in this field instead of 'Contact' or 'Via' headers
- * it's up to the transport layer to copy it to these headers */
- request->sigcomp_id = tsk_strdup(self->ss->sigcomp_id);
- }
-
-
- TSK_OBJECT_SAFE_FREE(request_uri);
- TSK_OBJECT_SAFE_FREE(from_uri);
- TSK_OBJECT_SAFE_FREE(to_uri);
-
- return request;
-}
-
-
-/** Sends a SIP/IMS request. This function is responsible for transaction creation.
- *
- * @param self The parent dialog. All callback events will be notified to this dialog.
- * @param request The request to send.
- *
- * @return Zero if succeed and no-zero error code otherwise.
-**/
-int tsip_dialog_request_send(const tsip_dialog_t *self, tsip_request_t* request)
-{
- int ret = -1;
-
- if(self && TSIP_DIALOG_GET_STACK(self)){
- const tsip_transac_layer_t *layer = TSIP_DIALOG_GET_STACK(self)->layer_transac;
- if(layer){
- /* Create new transaction. The new transaction will be added to the transaction layer.
- The transaction has all information to create the right transaction type (NICT or ICT).
- As this is an outgoing request ==> It shall be a client transaction (NICT or ICT).
- For server transactions creation see @ref tsip_dialog_response_send.
- */
- tsip_transac_t *transac = tsip_transac_layer_new(layer, tsk_true, request, TSIP_DIALOG(self));
-
- /* Set the transaction's dialog. All events comming from the transaction (timeouts, errors ...) will be signaled to this dialog.
- */
- if(transac){
- switch(transac->type)
- {
- case tsip_ict:
- case tsip_nict:
- {
- /* Start the newly create IC/NIC transaction */
- ret = tsip_transac_start(transac, request);
- break;
- }
- }
- tsk_object_unref(transac);
- }
- }
- }
- return ret;
-}
-
-tsip_response_t *tsip_dialog_response_new(const tsip_dialog_t *self, short status, const char* phrase, const tsip_request_t* request)
-{
- /* Reponse is created as per RFC 3261 subclause 8.2.6 and (headers+tags) are copied
- * as per subclause 8.2.6.2.
- */
- tsip_response_t* response;
- if((response = tsip_response_new(status, phrase, request))){
- /* Is there a To tag? */
- if(response->To && !response->To->tag){
- response->To->tag = tsk_strdup(self->tag_local);
- }
- /* Contact Header (for 101-299 reponses) */
- if(self->uri_local && TSIP_RESPONSE_CODE(response) >= 101 && TSIP_RESPONSE_CODE(response) <= 299){
- char* contact = tsk_null;
- tsip_header_Contacts_L_t *hdr_contacts;
-
- tsk_sprintf(&contact, "m: <%s:%s@%s:%d>\r\n", "sip", self->uri_local->user_name, "127.0.0.1", 5060);
- hdr_contacts = tsip_header_Contact_parse(contact, tsk_strlen(contact));
- if(!TSK_LIST_IS_EMPTY(hdr_contacts)){
- response->Contact = tsk_object_ref(hdr_contacts->head->data);
- response->update = tsk_true; /* Now signal that the message should be updated by the transport layer (Contact header) */
- }
- TSK_OBJECT_SAFE_FREE(hdr_contacts);
- TSK_FREE(contact);
- }
-
- /* SigComp */
- if(self->ss->sigcomp_id){
- /* should be added in this field instead of 'Contact' or 'Via' headers
- * it's up to the transport layer to copy it to these headers */
- response->sigcomp_id = tsk_strdup(self->ss->sigcomp_id);
- }
- }
- return response;
-}
-
-int tsip_dialog_response_send(const tsip_dialog_t *self, tsip_response_t* response)
-{
- int ret = -1;
-
- if(self && TSIP_DIALOG_GET_STACK(self)){
- const tsip_transac_layer_t *layer = TSIP_DIALOG_GET_STACK(self)->layer_transac;
- if(layer){
- /* As this is a response ...then use the associate server transaction */
- tsip_transac_t *transac = tsip_transac_layer_find_server(layer, response);
- if(transac){
- ret = transac->callback(transac, tsip_transac_outgoing_msg, response);
- tsk_object_unref(transac);
- }
- else{
- TSK_DEBUG_ERROR("Failed to find associated server transaction.");
- // Send "408 Request Timeout" (should be done by the transaction layer)?
- }
- }
- }
- else{
- TSK_DEBUG_ERROR("Invalid parameter");
- }
- return ret;
-}
-
-int tsip_dialog_apply_action(tsip_message_t* message, const tsip_action_t* action)
-{
- const tsk_list_item_t* item;
-
- if(!message || !action){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* SIP headers */
- tsk_list_foreach(item, action->headers){
- TSIP_MESSAGE_ADD_HEADER(message, TSIP_HEADER_DUMMY_VA_ARGS(TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value));
- }
- /* Payload */
- if(action->payload){
- tsip_message_add_content(message, tsk_null, TSK_BUFFER_DATA(action->payload), TSK_BUFFER_SIZE(action->payload));
- }
-
- return 0;
-}
-
-/**
- * Gets the number of milliseconds to wait before retransmission.
- * e.g. ==> delay before refreshing registrations (REGISTER), subscribtions (SUBSCRIBE), publication (PUBLISH) ...
- *
- *
- * @param [in,out] self The calling dialog.
- * @param [in,out] response The SIP/IMS response containing the new delay (expires, subscription-state ...).
- *
- * @return Zero if succeed and no-zero error code otherwise.
-**/
-int64_t tsip_dialog_get_newdelay(tsip_dialog_t *self, const tsip_response_t* response)
-{
- int64_t expires = self->expires;
- int64_t newdelay = expires; /* default value */
- const tsip_header_t* hdr;
- tsk_size_t i;
-
- /*== NOTIFY with subscription-state header with expires parameter.
- */
- if(TSIP_RESPONSE_IS_TO_NOTIFY(response)){
- const tsip_header_Subscription_State_t *hdr_state;
- if((hdr_state = (const tsip_header_Subscription_State_t*)tsip_message_get_header(response, tsip_htype_Subscription_State))){
- if(hdr_state->expires >0){
- expires = TSK_TIME_S_2_MS(hdr_state->expires);
- goto compute;
- }
- }
- }
-
- /*== Expires header.
- */
- if((hdr = tsip_message_get_header(response, tsip_htype_Expires))){
- expires = TSK_TIME_S_2_MS(((const tsip_header_Expires_t*)hdr)->delta_seconds);
- goto compute;
- }
-
- /*== Contact header.
- */
- for(i=0; (hdr = tsip_message_get_headerAt(response, tsip_htype_Contact, i)); i++){
- const tsip_header_Contact_t* contact = (const tsip_header_Contact_t*)hdr;
- if(contact && contact->uri)
- {
- tsip_uri_t* contactUri = tsip_stack_get_contacturi(TSIP_DIALOG_GET_STACK(self), tsk_params_get_param_value(contact->uri->params, "transport"));
- if(contactUri)
- {
- if(tsk_strequals(contact->uri->user_name, contactUri->user_name)
- && tsk_strequals(contact->uri->host, contactUri->host)
- && contact->uri->port == contactUri->port)
- {
- if(contact->expires>=0){ /* No expires parameter ==> -1*/
- expires = TSK_TIME_S_2_MS(contact->expires);
-
- TSK_OBJECT_SAFE_FREE(contactUri);
- goto compute;
- }
- }
- TSK_OBJECT_SAFE_FREE(contactUri);
- }
- }
- }
-
- /*
- * 3GPP TS 24.229 -
- *
- * The UE shall reregister the public user identity either 600 seconds before the expiration time if the initial
- * registration was for greater than 1200 seconds, or when half of the time has expired if the initial registration
- * was for 1200 seconds or less.
- */
-compute:
- expires = TSK_TIME_MS_2_S(expires);
- newdelay = (expires > 1200) ? (expires - 600) : (expires/2);
-
- return TSK_TIME_S_2_MS(newdelay);
-}
-
-/**
- *
- * Updates the dialog state:
- * - Authorizations (using challenges from the @a response message)
- * - State (early, established, disconnected, ...)
- * - Routes (and Service-Route)
- * - Target (remote)
- * - ...
- *
- * @param [in,out] self The calling dialog.
- * @param [in,out] response The SIP/IMS response from which to get the new information.
- *
- * @return Zero if succeed and no-zero error code otherwise.
-**/
-int tsip_dialog_update(tsip_dialog_t *self, const tsip_response_t* response)
-{
- if(self && TSIP_MESSAGE_IS_RESPONSE(response) && response->To){
- short code = TSIP_RESPONSE_CODE(response);
- const char *tag = response->To->tag;
-
- /*
- * 1xx (!100) or 2xx
- */
- /*
- * 401 or 407 or 421 or 494
- */
- if(code == 401 || code == 407 || code == 421 || code == 494)
- {
- tsk_bool_t acceptNewVector;
-
- /* 3GPP IMS - Each authentication vector is used only once.
- * ==> Re-registration/De-registration ==> Allow 401/407 challenge.
- */
- acceptNewVector = (TSIP_RESPONSE_IS_TO_REGISTER(response) && self->state == tsip_established);
- return tsip_dialog_update_challenges(self, response, acceptNewVector);
- }
- else if(100 < code && code < 300)
- {
- tsip_dialog_state_t state = self->state;
-
- /* 1xx */
- if(code <= 199){
- if(tsk_strempty(response->To->tag)){
- TSK_DEBUG_ERROR("Invalid tag parameter");
- return -1;
- }
- state = tsip_early;
- }
- /* 2xx */
- else{
- state = tsip_established;
- }
-
- /* Remote target */
- {
- /* RFC 3261 12.2.1.2 Processing the Responses
- When a UAC receives a 2xx response to a target refresh request, it
- MUST replace the dialog's remote target URI with the URI from the
- Contact header field in that response, if present.
-
- FIXME: Because PRACK/UPDATE sent before the session is established MUST have
- the rigth target URI to be delivered to the UAS ==> Do not not check that we are connected
- */
- if(!TSIP_RESPONSE_IS_TO_REGISTER(response) && response->Contact && response->Contact->uri){
- TSK_OBJECT_SAFE_FREE(self->uri_remote_target);
- self->uri_remote_target = tsip_uri_clone(response->Contact->uri, tsk_true, tsk_false);
- }
- }
-
- /* Route sets */
- {
- tsk_size_t index;
- const tsip_header_Record_Route_t *recordRoute;
- tsip_header_Record_Route_t *route;
-
- TSK_OBJECT_SAFE_FREE(self->record_routes);
-
- for(index = 0; (recordRoute = (const tsip_header_Record_Route_t *)tsip_message_get_headerAt(response, tsip_htype_Record_Route, index)); index++){
- if(!self->record_routes){
- self->record_routes = tsk_list_create();
- }
- if((route = tsk_object_ref((void*)recordRoute))){
- tsk_list_push_front_data(self->record_routes, (void**)&route); /* Copy reversed. */
- }
- }
- }
-
-
- /* cseq + tags + ... */
- if(self->state == tsip_established && tsk_striequals(self->tag_remote, tag)){
- return 0;
- }
- else{
- if(!TSIP_RESPONSE_IS_TO_REGISTER(response) && !TSIP_RESPONSE_IS_TO_PUBLISH(response)){ /* REGISTER and PUBLISH don't establish dialog */
- tsk_strupdate(&self->tag_remote, tag);
- }
-#if 0 // PRACK and BYE will have same CSeq value ==> Let CSeq value to be incremented by "tsip_dialog_request_new()"
- self->cseq_value = response->CSeq ? response->CSeq->seq : self->cseq_value;
-#endif
- }
-
- self->state = state;
- return 0;
- }
- }
- return 0;
-}
-
-int tsip_dialog_update_2(tsip_dialog_t *self, const tsip_request_t* invite)
-{
- if(!self || !invite){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* Remote target */
- if(invite->Contact && invite->Contact->uri){
- TSK_OBJECT_SAFE_FREE(self->uri_remote_target);
- self->uri_remote_target = tsip_uri_clone(invite->Contact->uri, tsk_true, tsk_false);
- }
-
- /* cseq + tags + remote-uri */
- tsk_strupdate(&self->tag_remote, invite->From?invite->From->tag:"doubango");
- /* self->cseq_value = invite->CSeq ? invite->CSeq->seq : self->cseq_value; */
- if(invite->From && invite->From->uri){
- TSK_OBJECT_SAFE_FREE(self->uri_remote);
- self->uri_remote = tsk_object_ref(invite->From->uri);
- }
-
- /* Route sets */
- {
- tsk_size_t index;
- const tsip_header_Record_Route_t *recordRoute;
- tsip_header_Record_Route_t* route;
-
- TSK_OBJECT_SAFE_FREE(self->record_routes);
-
- for(index = 0; (recordRoute = (const tsip_header_Record_Route_t *)tsip_message_get_headerAt(invite, tsip_htype_Record_Route, index)); index++){
- if(!self->record_routes){
- self->record_routes = tsk_list_create();
- }
- if((route = tsk_object_ref((void*)recordRoute))){
- tsk_list_push_front_data(self->record_routes, (void**)&route); /* Copy non-reversed. */
- }
- }
- }
-
- self->state = tsip_established;
-
- return 0;
-}
-
-int tsip_dialog_getCKIK(tsip_dialog_t *self, AKA_CK_T *ck, AKA_IK_T *ik)
-{
- tsk_list_item_t *item;
- tsip_challenge_t *challenge;
-
- if(!self){
- return -1;
- }
-
- tsk_list_foreach(item, self->challenges)
- {
- if((challenge = item->data)){
- memcpy(*ck, challenge->ck, AKA_CK_SIZE);
- memcpy(*ik, challenge->ik, AKA_IK_SIZE);
- return 0;
- }
- }
- TSK_DEBUG_ERROR("No challenge found. Fail to set IK and CK.");
- return -2;
-}
-
-int tsip_dialog_update_challenges(tsip_dialog_t *self, const tsip_response_t* response, int acceptNewVector)
-{
- int ret = -1;
- tsk_size_t i;
-
- tsk_list_item_t *item;
-
- tsip_challenge_t *challenge;
-
- const tsip_header_WWW_Authenticate_t *WWW_Authenticate;
- const tsip_header_Proxy_Authenticate_t *Proxy_Authenticate;
-
- /* RFC 2617 - HTTP Digest Session
-
- * (A) The client response to a WWW-Authenticate challenge for a protection
- space starts an authentication session with that protection space.
- The authentication session lasts until the client receives another
- WWW-Authenticate challenge from any server in the protection space.
-
- (B) The server may return a 401 response with a new nonce value, causing the client
- to retry the request; by specifying stale=TRUE with this response,
- the server tells the client to retry with the new nonce, but without
- prompting for a new username and password.
- */
- /* RFC 2617 - 1.2 Access Authentication Framework
- The realm directive (case-insensitive) is required for all authentication schemes that issue a challenge.
- */
-
- /* FIXME: As we perform the same task ==> Use only one loop.
- */
-
- for(i =0; (WWW_Authenticate = (const tsip_header_WWW_Authenticate_t*)tsip_message_get_headerAt(response, tsip_htype_WWW_Authenticate, i)); i++){
- tsk_bool_t isnew = tsk_true;
-
- tsk_list_foreach(item, self->challenges){
- challenge = item->data;
- if(challenge->isproxy) continue;
-
- if(tsk_striequals(challenge->realm, WWW_Authenticate->realm) && (WWW_Authenticate->stale || acceptNewVector)){
- /*== (B) ==*/
- if((ret = tsip_challenge_update(challenge,
- WWW_Authenticate->scheme,
- WWW_Authenticate->realm,
- WWW_Authenticate->nonce,
- WWW_Authenticate->opaque,
- WWW_Authenticate->algorithm,
- WWW_Authenticate->qop)))
- {
- return ret;
- }
- else{
- isnew = tsk_false;
- continue;
- }
- }
- else{
- TSK_DEBUG_ERROR("Failed to handle new challenge");
- return -1;
- }
- }
-
- if(isnew){
- if((challenge = tsip_challenge_create(TSIP_DIALOG_GET_STACK(self),
- tsk_false,
- WWW_Authenticate->scheme,
- WWW_Authenticate->realm,
- WWW_Authenticate->nonce,
- WWW_Authenticate->opaque,
- WWW_Authenticate->algorithm,
- WWW_Authenticate->qop)))
- {
- tsk_list_push_back_data(self->challenges, (void**)&challenge);
- }
- else{
- TSK_DEBUG_ERROR("Failed to handle new challenge");
- return -1;
- }
- }
- }
-
- for(i=0; (Proxy_Authenticate = (const tsip_header_Proxy_Authenticate_t*)tsip_message_get_headerAt(response, tsip_htype_Proxy_Authenticate, i)); i++){
- tsk_bool_t isnew = tsk_true;
-
- tsk_list_foreach(item, self->challenges){
- challenge = item->data;
- if(!challenge->isproxy){
- continue;
- }
-
- if(tsk_striequals(challenge->realm, Proxy_Authenticate->realm) && (Proxy_Authenticate->stale || acceptNewVector)){
- /*== (B) ==*/
- if((ret = tsip_challenge_update(challenge,
- Proxy_Authenticate->scheme,
- Proxy_Authenticate->realm,
- Proxy_Authenticate->nonce,
- Proxy_Authenticate->opaque,
- Proxy_Authenticate->algorithm,
- Proxy_Authenticate->qop)))
- {
- return ret;
- }
- else{
- isnew = tsk_false;
- continue;
- }
- }
- else{
- TSK_DEBUG_ERROR("Failed to handle new challenge");
- return -1;
- }
- }
-
- if(isnew){
- if((challenge = tsip_challenge_create(TSIP_DIALOG_GET_STACK(self),
- tsk_true,
- Proxy_Authenticate->scheme,
- Proxy_Authenticate->realm,
- Proxy_Authenticate->nonce,
- Proxy_Authenticate->opaque,
- Proxy_Authenticate->algorithm,
- Proxy_Authenticate->qop)))
- {
- tsk_list_push_back_data(self->challenges, (void**)&challenge);
- }
- else{
- TSK_DEBUG_ERROR("Failed to handle new challenge");
- return -1;
- }
- }
- }
- return 0;
-
-}
-
-int tsip_dialog_add_common_headers(const tsip_dialog_t *self, tsip_request_t* request)
-{
- tsk_bool_t earlyIMS = tsk_false;
- const tsip_uri_t* preferred_identity = tsk_null;
- const char* netinfo = tsk_null;
-
- if(!self || !request){
- return -1;
- }
-
- earlyIMS = TSIP_DIALOG_GET_STACK(self)->security.earlyIMS;
- preferred_identity = TSIP_DIALOG_GET_STACK(self)->identity.preferred;
-
- //
- // P-Preferred-Identity
- //
- if(preferred_identity){
- /* 3GPP TS 33.978 6.2.3.1 Procedures at the UE
- The UE shall use the temporary public user identity (IMSI-derived IMPU, cf. section 6.1.2) only in registration
- messages (i.e. initial registration, re-registration or de-registration), but not in any other type of SIP requests.
- */
- switch(request->line.request.request_type){
- case tsip_BYE:
- case tsip_INVITE:
- case tsip_OPTIONS:
- case tsip_SUBSCRIBE:
- case tsip_NOTIFY:
- case tsip_REFER:
- case tsip_MESSAGE:
- case tsip_PUBLISH:
- case tsip_REGISTER:
- {
- if(!earlyIMS || (earlyIMS && TSIP_REQUEST_IS_REGISTER(request))){
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_P_PREFERRED_IDENTITY_VA_ARGS(preferred_identity));
- }
- break;
- }
- }
- }
-
- //
- // P-Access-Network-Info
- //
- if(netinfo)
- {
- switch(request->line.request.request_type){
- case tsip_BYE:
- case tsip_INVITE:
- case tsip_OPTIONS:
- case tsip_REGISTER:
- case tsip_SUBSCRIBE:
- case tsip_NOTIFY:
- case tsip_PRACK:
- case tsip_INFO:
- case tsip_UPDATE:
- case tsip_REFER:
- case tsip_MESSAGE:
- case tsip_PUBLISH:
- {
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_P_ACCESS_NETWORK_INFO_VA_ARGS(netinfo));
- break;
- }
- }
- }
-
- return 0;
-}
-
-int tsip_dialog_init(tsip_dialog_t *self, tsip_dialog_type_t type, const char* call_id, tsip_ssession_t* ss, tsk_fsm_state_id curr, tsk_fsm_state_id term)
-{
- if(self){
- if(self->initialized){
- TSK_DEBUG_WARN("Dialog already initialized.");
- return -2;
- }
-
- self->state = tsip_initial;
- self->type = type;
- if(!self->record_routes){
- self->record_routes = tsk_list_create();
- }
- if(!self->challenges){
- self->challenges = tsk_list_create();
- }
-
- /* Sets default expires value. */
- self->expires = TSIP_SSESSION_EXPIRES_DEFAULT;
-
- if(call_id){
- /* "server-side" session */
- tsk_strupdate(&self->callid, call_id);
- }
- else{
- tsk_uuidstring_t uuid; /* Call-id is a random UUID */
- tsip_header_Call_ID_random(&uuid);
- tsk_strupdate(&self->callid, uuid);
- }
-
- /* ref SIP session */
- self->ss = tsk_object_ref(ss);
-
- /* Local tag */{
- tsk_istr_t tag;
- tsk_strrandom(&tag);
- tsk_strupdate(&self->tag_local, tag);
- }
-
- /* CSeq */
- self->cseq_value = (rand() + 1);
-
- /* FSM */
- self->fsm = tsk_fsm_create(curr, term);
-
- /*=== SIP Session ===*/
- if(self->ss != TSIP_SSESSION_INVALID_HANDLE){
-
- /* Expires */
- self->expires = ss->expires;
-
- /* From */
- self->uri_local = tsk_object_ref(call_id/* "server-side" */ ? ss->to : ss->from);
-
- /* To */
- if(ss->to){
- self->uri_remote = tsk_object_ref(ss->to);
- self->uri_remote_target = tsk_object_ref(ss->to); /* Request-URI. */
- }
- else{
- self->uri_remote = tsk_object_ref(ss->from);
- self->uri_remote_target = tsk_object_ref((void*)TSIP_DIALOG_GET_STACK(self)->network.realm);
- }
- }
- else{
- TSK_DEBUG_ERROR("Invalid SIP Session id.");
- }
-
- self->initialized = tsk_true;
- return 0;
- }
- return -1;
-}
-
-int tsip_dialog_fsm_act(tsip_dialog_t* self, tsk_fsm_action_id action_id, const tsip_message_t* message, const tsip_action_handle_t* action)
-{
- if(!self || !self->fsm){
- TSK_DEBUG_ERROR("Invalid parameter.");
- return -1;
- }
- return tsk_fsm_act(self->fsm, action_id, self, message, self, message, action);
-}
-
-int tsip_dialog_set_curr_action(tsip_dialog_t* self, const tsip_action_t* action)
-{
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter.");
- return -1;
- }
- TSK_OBJECT_SAFE_FREE(self->curr_action);
- if(action){
- self->curr_action = tsk_object_ref((void*)action);
- }
- return 0;
-}
-
-int tsip_dialog_set_lasterror(tsip_dialog_t* self, const char* error)
-{
- if(!self || tsk_strnullORempty(error)){
- TSK_DEBUG_ERROR("Invalid parameter.");
- return -1;
- }
-
- tsk_strupdate(&self->lasterror, error);
- return 0;
-}
-
-const char* tsip_dialog_get_lasterror(const tsip_dialog_t* self)
-{
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter.");
- return tsk_null;
- }
-
- return self->lasterror;
-}
-
-int tsip_dialog_hangup(tsip_dialog_t *self, const tsip_action_t* action)
-{
- if(self){
- if(self->state == tsip_established){
- return tsip_dialog_fsm_act(self, tsip_atype_hangup, tsk_null, action);
- }
- else{
- return tsip_dialog_fsm_act(self, tsip_atype_cancel, tsk_null, action);
- }
- }
- return -1;
-}
-
-int tsip_dialog_shutdown(tsip_dialog_t *self, const tsip_action_t* action)
-{
- if(self){
- return tsip_dialog_fsm_act(self, tsip_atype_shutdown, tsk_null, action);
- }
- return -1;
-}
-
-int tsip_dialog_remove(const tsip_dialog_t* self)
-{
- return tsip_dialog_layer_remove(TSIP_DIALOG_GET_STACK(self)->layer_dialog, TSIP_DIALOG(self));
-}
-
-int tsip_dialog_cmp(const tsip_dialog_t *d1, const tsip_dialog_t *d2)
-{
- if(d1 && d2){
- if(
- tsk_strequals(d1->callid, d2->callid)
- && (tsk_strequals(d1->tag_local, d2->tag_local))
- && (tsk_strequals(d1->tag_remote, d2->tag_remote))
- )
- {
- return 0;
- }
- }
- return -1;
-}
-
-int tsip_dialog_deinit(tsip_dialog_t *self)
-{
- if(self){
- if(!self->initialized){
- TSK_DEBUG_WARN("Dialog not initialized.");
- return -2;
- }
-
- /* Cancel all transactions associated to this dialog (do it here before the dialog becomes unsafe) */
- tsip_transac_layer_cancel_by_dialog(TSIP_DIALOG_GET_STACK(self)->layer_transac, self);
-
- TSK_OBJECT_SAFE_FREE(self->ss);
- TSK_OBJECT_SAFE_FREE(self->curr_action);
-
- TSK_OBJECT_SAFE_FREE(self->uri_local);
- TSK_FREE(self->tag_local);
- TSK_OBJECT_SAFE_FREE(self->uri_remote);
- TSK_FREE(self->tag_remote);
-
- TSK_OBJECT_SAFE_FREE(self->uri_remote_target);
-
- TSK_FREE(self->cseq_method);
- TSK_FREE(self->callid);
-
- TSK_FREE(self->lasterror);
-
- TSK_OBJECT_SAFE_FREE(self->record_routes);
- TSK_OBJECT_SAFE_FREE(self->challenges);
-
- TSK_OBJECT_SAFE_FREE(self->fsm);
-
- self->initialized = 0;
-
- return 0;
- }
- return -1;
-}
-
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.c
deleted file mode 100644
index 0c380be..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_invite.c
- * @brief SIP dialog INVITE as per RFC 3261.
- * The SOA machine is designed as per RFC 3264 and draft-ietf-sipping-sip-offeranswer-12.
- * MMTel services implementation follow 3GPP TS 24.173.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_invite.h"
-
-#include "tinysip/dialogs/tsip_dialog_invite.common.h"
-
-#include "tinysip/transports/tsip_transport_layer.h"
-
-#include "tinysip/headers/tsip_header_Allow.h"
-#include "tinysip/headers/tsip_header_Dummy.h"
-#include "tinysip/headers/tsip_header_Max_Forwards.h"
-#include "tinysip/headers/tsip_header_Min_SE.h"
-#include "tinysip/headers/tsip_header_RAck.h"
-#include "tinysip/headers/tsip_header_Require.h"
-#include "tinysip/headers/tsip_header_RSeq.h"
-#include "tinysip/headers/tsip_header_Session_Expires.h"
-#include "tinysip/headers/tsip_header_Supported.h"
-
-#include "tinysdp/parsers/tsdp_parser_message.h"
-
-#include "tsk_debug.h"
-
-// http://cdnet.stpi.org.tw/techroom/market/_pdf/2009/eetelecomm_09_009_OneVoiceProfile.pdf
-// 3GPP TS 26.114 (MMTel): Media handling and interaction
-// 3GPP TS 24.173 (MMTel): Supplementary Services
-//
-/* ======================== MMTel Supplementary Services ========================
-3GPP TS 24.607 : Originating Identification Presentation
-3GPP TS 24.608 : Terminating Identification Presentation
-3GPP TS 24.607 : Originating Identification Restriction
-3GPP TS 24.608 : Terminating Identification Restriction
-
-3GPP TS 24.604 : Communication Diversion Unconditional
-3GPP TS 24.604 : Communication Diversion on not Logged
-3GPP TS 24.604 : Communication Diversion on Busy
-3GPP TS 24.604 : Communication Diversion on not Reachable
-3GPP TS 24.604 : Communication Diversion on No Reply
-3GPP TS 24.611 : Barring of All Incoming Calls
-3GPP TS 24.611 : Barring of All Outgoing Calls
-3GPP TS 24.611 : Barring of Outgoing International Calls
-3GPP TS 24.611 : Barring of Incoming Calls - When Roaming
-3GPP TS 24.610 : Communication Hold
-3GPP TS 24.606 : Message Waiting Indication
-3GPP TS 24.615 : Communication Waiting
-3GPP TS 24.605 : Ad-Hoc Multi Party Conference
-*/
-
-/* ======================== internal functions ======================== */
-int send_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE, tsk_bool_t force_sdp);
-int send_PRACK(tsip_dialog_invite_t *self, const tsip_response_t* r1xx);
-int send_ACK(tsip_dialog_invite_t *self, const tsip_response_t* r2xxINVITE);
-int send_RESPONSE(tsip_dialog_invite_t *self, const tsip_request_t* request, short code, const char* phrase, tsk_bool_t force_sdp);
-int send_ERROR(tsip_dialog_invite_t* self, const tsip_request_t* request, short code, const char* phrase, const char* reason);
-int send_BYE(tsip_dialog_invite_t *self);
-int send_CANCEL(tsip_dialog_invite_t *self);
-int tsip_dialog_invite_OnTerminated(tsip_dialog_invite_t *self);
-
-/* ======================== external functions ======================== */
-extern int tsip_dialog_invite_stimers_cancel(tsip_dialog_invite_t* self);
-extern int tsip_dialog_invite_qos_timer_cancel(tsip_dialog_invite_t* self);
-extern int tsip_dialog_invite_qos_timer_schedule(tsip_dialog_invite_t* self);
-extern int tsip_dialog_invite_stimers_schedule(tsip_dialog_invite_t* self, uint64_t timeout);
-extern int tsip_dialog_invite_stimers_handle(tsip_dialog_invite_t* self, const tsip_message_t* message);
-extern int tsip_dialog_invite_hold_handle(tsip_dialog_invite_t* self, const tsip_request_t* rINVITEorUPDATE);
-
-/* ======================== transitions ======================== */
-static int x0000_Connected_2_Connected_X_oDTMF(va_list *app);
-static int x0000_Connected_2_Connected_X_oLMessage(va_list *app);
-static int x0000_Connected_2_Connected_X_iACK(va_list *app);
-static int x0000_Connected_2_Connected_X_iINVITEorUPDATE(va_list *app);
-
-
-int x0000_Any_2_Any_X_i1xx(va_list *app);
-int x0000_Any_2_Any_X_i401_407_INVITEorUPDATE(va_list *app);
-int x0000_Any_2_Any_X_i2xxINVITEorUPDATE(va_list *app);
-
-int x0000_Any_2_Any_X_iPRACK(va_list *app);
-int x0000_Any_2_Any_X_iOPTIONS(va_list *app);
-int x0000_Any_2_Trying_X_oBYE(va_list *app); /* If not Connected => Cancel will be called instead. See tsip_dialog_hangup() */
-int x0000_Any_2_Terminated_X_iBYE(va_list *app);
-int x0000_Any_2_Trying_X_shutdown(va_list *app);
-
-int x9998_Any_2_Any_X_transportError(va_list *app);
-int x9999_Any_2_Any_X_Error(va_list *app);
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_is_resp2INVITE(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return TSIP_RESPONSE_IS_TO_INVITE(message);
-}
-static tsk_bool_t _fsm_cond_is_resp2UPDATE(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return TSIP_RESPONSE_IS_TO_UPDATE(message);
-}
-static tsk_bool_t _fsm_cond_is_resp2BYE(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return TSIP_RESPONSE_IS_TO_BYE(message);
-}
-static tsk_bool_t _fsm_cond_is_resp2PRACK(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return TSIP_RESPONSE_IS_TO_PRACK(message);
-}
-
-/* ======================== actions ======================== */
-/* #include "tinysip/dialogs/tsip_dialog_invite.common.h" */
-
-/* ======================== states ======================== */
-/* #include "tinysip/dialogs/tsip_dialog_invite.common.h" */
-
-/* Client-Side dialog */
-extern int tsip_dialog_invite_client_init(tsip_dialog_invite_t *self);
-/* Server-Side dialog */
-extern int tsip_dialog_invite_server_init(tsip_dialog_invite_t *self);
-/* 3GPP TS 24.610: Communication Hold */
-extern int tsip_dialog_invite_hold_init(tsip_dialog_invite_t *self);
-/* RFC 4028: Session Timers */
-extern int tsip_dialog_invite_stimers_init(tsip_dialog_invite_t *self);
-/* RFC 3312: Integration of Resource Management and Session Initiation Protocol (SIP) */
-extern int tsip_dialog_invite_qos_init(tsip_dialog_invite_t *self);
-
-int tsip_dialog_invite_event_callback(const tsip_dialog_invite_t *self, tsip_dialog_event_type_t type, const tsip_message_t *msg)
-{
- int ret = -1;
-
- switch(type)
- {
- case tsip_dialog_i_msg:
- {
- if(msg){
- if(TSIP_MESSAGE_IS_RESPONSE(msg)){ /* Response */
- if(TSIP_RESPONSE_IS_1XX(msg)){ // 100-199
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_i1xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS_2XX(msg)){ // 200-299
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_i2xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_CODE(msg) == 401 || TSIP_RESPONSE_CODE(msg) == 407){ // 401,407
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_i401_i407, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_CODE(msg) == 422){ // 422
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_i422, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS_3456(msg)){ // 300-699
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_i300_to_i699, msg, tsk_null);
- }
- else; // Ignore
- }
- else{ /* Request */
- if(TSIP_REQUEST_IS_INVITE(msg)){ // INVITE
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_iINVITE, msg, tsk_null);
- }
- else if(TSIP_REQUEST_IS_UPDATE(msg)){ // UPDATE
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_iUPDATE, msg, tsk_null);
- }
- else if(TSIP_REQUEST_IS_PRACK(msg)){ // PRACK
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_iPRACK, msg, tsk_null);
- }
- else if(TSIP_REQUEST_IS_ACK(msg)){ // ACK
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_iACK, msg, tsk_null);
- }
- else if(TSIP_REQUEST_IS_OPTIONS(msg)){ // OPTIONS
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_iOPTIONS, msg, tsk_null);
- }
- else if(TSIP_REQUEST_IS_BYE(msg)){ // BYE
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_iBYE, msg, tsk_null);
- }
- else if(TSIP_REQUEST_IS_CANCEL(msg)){ // CANCEL
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_iCANCEL, msg, tsk_null);
- }
- }
- }
- break;
- }
-
- case tsip_dialog_canceled:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_oCANCEL, msg, tsk_null);
- break;
- }
-
- case tsip_dialog_terminated:
- case tsip_dialog_timedout:
- case tsip_dialog_error:
- case tsip_dialog_transport_error:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_transporterror, msg, tsk_null);
- break;
- }
- }
-
- return ret;
-}
-
-/**Timer manager callback.
- *
- * @param self The owner of the signaled timer.
- * @param timer_id The identifier of the signaled timer.
- *
- * @return Zero if succeed and non-zero error code otherwise.
-**/
-int tsip_dialog_invite_timer_callback(const tsip_dialog_invite_t* self, tsk_timer_id_t timer_id)
-{
- int ret = -1;
-
- if(self){
- if(timer_id == self->stimers.timer.id){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_timerRefresh, tsk_null, tsk_null);
- }
- else if(timer_id == self->timer100rel.id){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_timer100rel, tsk_null, tsk_null);
- }
- else if(timer_id == self->qos.timer.id){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_timerRSVP, tsk_null, tsk_null);
- }
- else if(timer_id == self->timershutdown.id){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_shutdown_timedout, tsk_null, tsk_null);
- }
- }
- return ret;
-}
-
-tsip_dialog_invite_t* tsip_dialog_invite_create(const tsip_ssession_handle_t* ss, const char* call_id)
-{
- return tsk_object_new(tsip_dialog_invite_def_t, ss, call_id);
-}
-
-int tsip_dialog_invite_init(tsip_dialog_invite_t *self)
-{
- /* special cases (fsm) should be tried first */
-
- /* Client-Side dialog */
- tsip_dialog_invite_client_init(self);
- /* Server-Side dialog */
- tsip_dialog_invite_server_init(self);
- /* 3GPP TS 24.610: Communication Hold */
- tsip_dialog_invite_hold_init(self);
- /* RFC 4028: Session Timers */
- tsip_dialog_invite_stimers_init(self);
- /* RFC 3312: Integration of Resource Management and Session Initiation Protocol (SIP) */
- tsip_dialog_invite_qos_init(self);
-
- /* Initialize the state machine (all other cases) */
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Started ===
- */
- // Started -> (Any) -> Started
- TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_dialog_invite_Started_2_Started_X_any"),
-
- /*=======================
- * === Connected ===
- */
- // Connected -> (Send DTMF) -> Connected
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_dtmf_send, _fsm_state_Connected, x0000_Connected_2_Connected_X_oDTMF, "x0000_Connected_2_Connected_X_oDTMF"),
- // Connected -> (Send MSRP message) -> Connected
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_msrp_send_msg, _fsm_state_Connected, x0000_Connected_2_Connected_X_oLMessage, "x0000_Connected_2_Connected_X_oLMessage"),
- // Connected -> (iACK) -> Connected
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_iACK, _fsm_state_Connected, x0000_Connected_2_Connected_X_iACK, "x0000_Connected_2_Connected_X_iACK"),
- // Connected -> (iINVITE) -> Connected
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_iINVITE, _fsm_state_Connected, x0000_Connected_2_Connected_X_iINVITEorUPDATE, "x0000_Connected_2_Connected_X_iINVITE"),
- // Connected -> (iUPDATE) -> Connected
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_iUPDATE, _fsm_state_Connected, x0000_Connected_2_Connected_X_iINVITEorUPDATE, "x0000_Connected_2_Connected_X_iUPDATE"),
-
- /*=======================
- * === BYE/SHUTDOWN ===
- */
- // Any -> (oBYE) -> Trying
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_oBYE, _fsm_state_Trying, x0000_Any_2_Trying_X_oBYE, "x0000_Any_2_Trying_X_oBYE"),
- // Any -> (oBYE) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_iBYE, _fsm_state_Terminated, x0000_Any_2_Terminated_X_iBYE, "x0000_Any_2_Terminated_X_iBYE"),
- // Trying -> (i2xx BYE) -> Terminated
- TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_i2xx, _fsm_cond_is_resp2BYE, _fsm_state_Terminated, tsk_null, "x0000_Trying_2_Terminated_X_i2xxBYE"),
- // Trying -> (i3xx-i6xx BYE) -> Terminated
- TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_i300_to_i699, _fsm_cond_is_resp2BYE, _fsm_state_Terminated, tsk_null, "x0000_Trying_2_Terminated_X_i2xxTOi6xxBYE"),
- // Any -> (Shutdown) -> Trying
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_oShutdown, _fsm_state_Trying, x0000_Any_2_Trying_X_shutdown, "x0000_Any_2_Trying_X_shutdown"),
- // Any -> (shutdown timedout) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_shutdown_timedout, _fsm_state_Terminated, tsk_null, "tsip_dialog_invite_shutdown_timedout"),
-
-
- /*=======================
- * === Any ===
- */
- // Any -> (i1xx) -> Any
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_i1xx, tsk_fsm_state_any, x0000_Any_2_Any_X_i1xx, "x0000_Any_2_Any_X_i1xx"),
- // Any -> (i401/407)
- //
- // Any -> (iPRACK) -> Any
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_iPRACK, tsk_fsm_state_any, x0000_Any_2_Any_X_iPRACK, "x0000_Any_2_Any_X_iPRACK"),
- // Any -> (iOPTIONS) -> Any
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_iOPTIONS, tsk_fsm_state_any, x0000_Any_2_Any_X_iOPTIONS, "x0000_Any_2_Any_X_iOPTIONS"),
- // Any -> (i2xx INVITE) -> Any
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_i2xx, _fsm_cond_is_resp2INVITE, tsk_fsm_state_any, x0000_Any_2_Any_X_i2xxINVITEorUPDATE, "x0000_Any_2_Any_X_i2xxINVITE"),
- // Any -> (i2xx UPDATE) -> Any
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_i2xx, _fsm_cond_is_resp2UPDATE, tsk_fsm_state_any, x0000_Any_2_Any_X_i2xxINVITEorUPDATE, "x0000_Any_2_Any_X_i2xxUPDATE"),
- // Any -> (i401/407 INVITE) -> Any
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_i401_i407, _fsm_cond_is_resp2INVITE, tsk_fsm_state_any, x0000_Any_2_Any_X_i401_407_INVITEorUPDATE, "x0000_Any_2_Any_X_i401_407_INVITE"),
- // Any -> (i401/407 UPDATE) -> Any
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_i401_i407, _fsm_cond_is_resp2UPDATE, tsk_fsm_state_any, x0000_Any_2_Any_X_i401_407_INVITEorUPDATE, "x0000_Any_2_Any_X_i401_407_UPDATE"),
- // Any -> (i2xx PRACK) -> Any
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_i2xx, _fsm_cond_is_resp2PRACK, tsk_fsm_state_any, tsk_null, "x0000_Any_2_Any_X_i2xxPRACK"), // FIXME: remove, now we have server
- // Any -> (transport error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, x9998_Any_2_Any_X_transportError, "x9998_Any_2_Any_X_transportError"),
- // Any -> (transport error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, x9999_Any_2_Any_X_Error, "x9999_Any_2_Any_X_Error"),
-
- TSK_FSM_ADD_NULL());
-
- /* Sets callback function */
- TSIP_DIALOG(self)->callback = TSIP_DIALOG_EVENT_CALLBACK_F(tsip_dialog_invite_event_callback);
-
- /* Timers */
- self->timer100rel.id = TSK_INVALID_TIMER_ID;
- self->stimers.timer.id = TSK_INVALID_TIMER_ID;
- self->timershutdown.id = TSK_INVALID_TIMER_ID;
- self->timershutdown.timeout = TSIP_DIALOG_SHUTDOWN_TIMEOUT;
-
- return 0;
-}
-
-// start sending
-int tsip_dialog_invite_start(tsip_dialog_invite_t *self)
-{
- int ret = -1;
- if(self && !TSIP_DIALOG(self)->running){
- if(!(ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_oINVITE, tsk_null, tsk_null))){
- TSIP_DIALOG(self)->running = tsk_true;
- }
- }
- return ret;
-}
-
-int tsip_dialog_invite_process_ro(tsip_dialog_invite_t *self, const tsip_message_t* message)
-{
- tsdp_message_t* sdp_ro = tsk_null;
- int ret = 0;
-
- if(!self || !message){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- /* Parse SDP content */
- if(TSIP_MESSAGE_HAS_CONTENT(message)){
- if(tsk_striequals("application/sdp", TSIP_MESSAGE_CONTENT_TYPE(message))){
- if(!(sdp_ro = tsdp_message_parse(TSIP_MESSAGE_CONTENT_DATA(message), TSIP_MESSAGE_CONTENT_DATA_LENGTH(message)))){
- TSK_DEBUG_ERROR("Failed to parse remote sdp message");
- return -2;
- }
- }
- else{
- TSK_DEBUG_ERROR("[%s] content-type is not supportted", TSIP_MESSAGE_CONTENT_TYPE(message));
- return -3;
- }
- }
- else{
- if(TSIP_DIALOG(self)->state == tsip_initial && TSIP_REQUEST_IS_INVITE(message)){ /* Bodiless initial INVITE */
- TSIP_DIALOG_GET_SS(self)->media.type = tmedia_audio; // Default media for initial INVITE to send with the first reliable answer
- }
- else{
- return 0;
- }
- }
-
- /* Create session Manager if not already done */
- if(!self->msession_mgr){
- if(sdp_ro){
- TSIP_DIALOG_GET_SS(self)->media.type = tmedia_type_from_sdp(sdp_ro);
- }
- self->msession_mgr = tmedia_session_mgr_create(TSIP_DIALOG_GET_SS(self)->media.type, TSIP_DIALOG_GET_STACK(self)->network.local_ip,
- TNET_SOCKET_TYPE_IS_IPV6(TSIP_DIALOG_GET_STACK(self)->network.proxy_cscf_type), (sdp_ro == tsk_null));
- if(TSIP_DIALOG_GET_STACK(self)->natt.ctx){
- tmedia_session_mgr_set_natt_ctx(self->msession_mgr, TSIP_DIALOG_GET_STACK(self)->natt.ctx, TSIP_DIALOG_GET_STACK(self)->network.aor.ip);
- }
- }
-
- if(sdp_ro){
- if((ret = tmedia_session_mgr_set_ro(self->msession_mgr, sdp_ro))){
- TSK_DEBUG_ERROR("Failed to set remote offer");
- goto bail;
- }
- }
-
- /* start session manager */
- if(!self->msession_mgr->started && (self->msession_mgr->sdp.lo && self->msession_mgr->sdp.ro)){
- /* Set MSRP Callback */
- if((self->msession_mgr->type & tmedia_msrp) == tmedia_msrp){
- tmedia_session_mgr_set_msrp_cb(self->msession_mgr, TSIP_DIALOG_GET_SS(self)->userdata, TSIP_DIALOG_GET_SS(self)->media.msrp.callback);
- }
- /* starts */
- ret = tmedia_session_mgr_start(self->msession_mgr);
- if(ret == 0 && TSIP_DIALOG(self)->state == tsip_early){
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_m_early_media,
- TSIP_RESPONSE_CODE(message), TSIP_RESPONSE_PHRASE(message), message);
- }
- }
-
-bail:
- TSK_OBJECT_SAFE_FREE(sdp_ro);
-
- return ret;
-}
-
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-int x0000_Connected_2_Connected_X_oDTMF(va_list *app)
-{
- int ret;
- tsip_dialog_invite_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_invite_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- if(action){
- ret = tmedia_session_mgr_send_dtmf(self->msession_mgr, action->dtmf.event);
- }
- else{
- TSK_DEBUG_ERROR("Invalid action");
- }
-
- return 0; /* always */
-}
-
-int x0000_Connected_2_Connected_X_oLMessage(va_list *app)
-{
- int ret;
- tsip_dialog_invite_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_invite_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- if(action && action->payload){
- ret = tmedia_session_mgr_send_message(self->msession_mgr, action->payload->data, action->payload->size,
- action->media.params);
- }
- else{
- TSK_DEBUG_ERROR("Invalid action");
- }
-
- return 0;
-}
-
-/* Connected -> (iACK) -> Connected */
-int x0000_Connected_2_Connected_X_iACK(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_request_t *rACK = va_arg(*app, const tsip_request_t *);
- int ret;
-
- // Nothing to do (in future will be used to ensure the session)
-
- /* Process remote offer */
- if((ret = tsip_dialog_invite_process_ro(self, rACK))){
- /* Send error */
- return ret;
- }
-
- /* alert the user */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_i_request,
- tsip_event_code_dialog_request_incoming, "Incoming Request.", rACK);
-
- return 0;
-}
-
-/* Connected -> (iINVITE or iUPDATE) -> Connected */
-int x0000_Connected_2_Connected_X_iINVITEorUPDATE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_request_t *rINVITEorUPDATE = va_arg(*app, const tsip_request_t *);
-
- int ret = 0;
-
- /* process remote offer */
- if((ret = tsip_dialog_invite_process_ro(self, rINVITEorUPDATE))){
- /* Send error */
- return ret;
- }
-
- /* Send 200 OK */
- ret = send_RESPONSE(self, rINVITEorUPDATE, 200, "OK",
- (self->msession_mgr && (self->msession_mgr->ro_changed || self->msession_mgr->state_changed)));
-
- /* session timers */
- if(self->stimers.timer.timeout){
- tsip_dialog_invite_stimers_handle(self, rINVITEorUPDATE);
- }
-
- /* hold/resume */
- tsip_dialog_invite_hold_handle(self, rINVITEorUPDATE);
-
- /* alert the user */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_i_request,
- tsip_event_code_dialog_request_incoming, "Incoming Request.", rINVITEorUPDATE);
-
-
- return ret;
-}
-
-/* Any -> (iPRACK) -> Any */
-int x0000_Any_2_Any_X_iPRACK(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_request_t *rPRACK = va_arg(*app, const tsip_request_t *);
-
- const tsip_header_RAck_t* RAck;
-
- if((RAck = (const tsip_header_RAck_t*)tsip_message_get_header(rPRACK, tsip_htype_RAck))){
- if((RAck->seq == self->rseq) &&
- (tsk_striequals(RAck->method, self->last_o1xxrel->CSeq->method)) &&
- (RAck->cseq == self->last_o1xxrel->CSeq->seq)){
-
- ++self->rseq;
- return send_RESPONSE(self, rPRACK, 200, "OK", tsk_false);
- }
- }
-
- /* Send 488 */
- return send_ERROR(self, self->last_iInvite, 488, "Not Acceptable", "SIP; cause=488; text=\"Failed to match PRACK request\"");
-}
-
-/* Any -> (iOPTIONS) -> Any */
-int x0000_Any_2_Any_X_iOPTIONS(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_request_t *rOPTIONS = va_arg(*app, const tsip_request_t *);
-
- /* Alert user */
-
- /* Send 2xx */
- send_RESPONSE(self, rOPTIONS, 200, "OK", tsk_false);
-
- return 0;
-}
-
-
-/* Any --> (i401/407 INVITE or UPDATE) --> Any */
-int x0000_Any_2_Any_X_i401_407_INVITEorUPDATE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
- int ret;
-
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), response))){
- /* Alert the user. */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_ao_request,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return ret;
- }
-
- return send_INVITEorUPDATE(self, TSIP_RESPONSE_IS_TO_INVITE(response), tsk_false);
-}
-
-/* Any --> (i2xx INVITE or i2xx UPDATE) --> Any */
-int x0000_Any_2_Any_X_i2xxINVITEorUPDATE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_response_t *r2xx = va_arg(*app, const tsip_response_t *);
- int ret = 0;
-
- /* Update the dialog state */
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), r2xx))){
- return ret;
- }
-
- /* session timers */
- if(self->stimers.timer.timeout){
- tsip_dialog_invite_stimers_handle(self, r2xx);
- }
-
- /* Process remote offer */
- if((ret = tsip_dialog_invite_process_ro(self, r2xx))){
- /* Send error */
- return ret;
- }
-
- /* send ACK */
- if(TSIP_RESPONSE_IS_TO_INVITE(r2xx)){
- ret = send_ACK(self, r2xx);
- }
-
- return ret;
-}
-
-
-/* Any -> (oBYE) -> Trying */
-int x0000_Any_2_Trying_X_oBYE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminating, "Terminating dialog");
-
- /* send BYE */
- return send_BYE(self);
-}
-
-/* Any -> (iBYE) -> Terminated */
-int x0000_Any_2_Terminated_X_iBYE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_request_t *rBYE = va_arg(*app, const tsip_request_t *);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), "Call Terminated");
-
- /* send 200 OK */
- return send_RESPONSE(self, rBYE, 200, "OK", tsk_false);
-}
-
-/* Any -> Shutdown -> Terminated */
-int x0000_Any_2_Trying_X_shutdown(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
-
- /* schedule shutdow timeout */
- TSIP_DIALOG_INVITE_TIMER_SCHEDULE(shutdown);
-
- /* alert user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminating, "Terminating dialog");
-
- if(TSIP_DIALOG(self)->state == tsip_established){
- return send_BYE(self);
- }
- else if(TSIP_DIALOG(self)->state == tsip_early){
- return send_CANCEL(self);
- }
-
- return 0;
-}
-
-
-/* Any -> (i1xx) -> Any */
-int x0000_Any_2_Any_X_i1xx(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_response_t *r1xx = va_arg(*app, const tsip_response_t *);
- int ret = 0;
-
- /* Update the dialog state */
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), r1xx))){
- return ret;
- }
-
- /* RFC 3262 - 4 UAC Behavior
- If a provisional response is received for an initial request, and
- that response contains a Require header field containing the option
- tag 100rel, the response is to be sent reliably. If the response is
- a 100 (Trying) (as opposed to 101 to 199), this option tag MUST be
- ignored, and the procedures below MUST NOT be used.
-
- Assuming the response is to be transmitted reliably, the UAC MUST
- create a new request with method PRACK. This request is sent within
- the dialog associated with the provisional response (indeed, the
- provisional response may have created the dialog). PRACK requests
- MAY contain bodies, which are interpreted according to their type and
- disposition.
-
- Note that the PRACK is like any other non-INVITE request within a
- dialog. In particular, a UAC SHOULD NOT retransmit the PRACK request
- when it receives a retransmission of the provisional response being
- acknowledged, although doing so does not create a protocol error.
- */
- if((TSIP_RESPONSE_CODE(r1xx) >= 101 && TSIP_RESPONSE_CODE(r1xx) <=199) && tsip_message_required(r1xx, "100rel")){
- /* Process Remote offer */
- if((ret = tsip_dialog_invite_process_ro(self, r1xx))){
- /* Send Error */
- return ret;
- }
-
- if((ret = send_PRACK(self, r1xx))){
- return ret;
- }
- }
-
- /* QoS Reservation */
- if((self->qos.timer.id == TSK_INVALID_TIMER_ID) && tsip_message_required(r1xx, "precondition") && !tmedia_session_mgr_canresume(self->msession_mgr)){
- tsip_dialog_invite_qos_timer_schedule(self);
- }
-
- /* alert the user */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_ao_request,
- TSIP_RESPONSE_CODE(r1xx), TSIP_RESPONSE_PHRASE(r1xx), r1xx);
-
- return ret;
-}
-
-int x9998_Any_2_Any_X_transportError(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), "Transport error");
-
- return 0;
-}
-
-int x9999_Any_2_Any_X_Error(va_list *app)
-{
- return 0;
-}
-
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-
-// send INVITE/UPDATE request
-int send_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE, tsk_bool_t force_sdp)
-{
- int ret = -1;
- tsip_request_t *request = tsk_null;
- tsk_bool_t bodiless = tsk_false;
-
-#if BODILESS_INVITE
- if(TSIP_DIALOG(self)->state == tsip_initial){
- bodiless = tsk_true;
- }
-#endif
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- goto bail;
- }
-
- if((request = tsip_dialog_request_new(TSIP_DIALOG(self), is_INVITE ? "INVITE" : "UPDATE"))){
-
- /* apply action params to the request (will add a content if the action contains one) */
- if(TSIP_DIALOG(self)->curr_action){
- tsip_dialog_apply_action(request, TSIP_DIALOG(self)->curr_action);
- }
-
- if(!bodiless){
- /* add our payload if current action does not have one */
- if((force_sdp || is_INVITE) || ((self->msession_mgr && self->msession_mgr->state_changed) || (TSIP_DIALOG(self)->state == tsip_initial))){
- if(!TSIP_DIALOG(self)->curr_action || !TSIP_DIALOG(self)->curr_action->payload){
- const tsdp_message_t* sdp_lo;
- char* sdp;
- if((sdp_lo = tmedia_session_mgr_get_lo(self->msession_mgr)) && (sdp = tsdp_message_tostring(sdp_lo))){
- tsip_message_add_content(request, "application/sdp", sdp, tsk_strlen(sdp));
- TSK_FREE(sdp);
- }
- }
- }
- }
-
- /* Session timers */
- if(self->stimers.timer.timeout){
- if(self->require.timer){
- tsip_message_add_headers(request,
- TSIP_HEADER_SESSION_EXPIRES_VA_ARGS(self->stimers.timer.timeout, tsk_striequals(self->stimers.refresher, "uas")),
- TSIP_HEADER_REQUIRE_VA_ARGS("timer"),
- tsk_null
- );
- }
- else if(self->supported.timer){
- tsip_message_add_headers(request,
- TSIP_HEADER_SESSION_EXPIRES_VA_ARGS(self->stimers.timer.timeout, tsk_striequals(self->stimers.refresher, "uas")),
- TSIP_HEADER_SUPPORTED_VA_ARGS("timer"),
- tsk_null
- );
- }
-
- }
-
- if(self->stimers.minse){
- tsip_message_add_headers(request,
- TSIP_HEADER_MIN_SE_VA_ARGS(self->stimers.minse),
- tsk_null
- );
- }
-
- /* 100rel */
- if(self->require._100rel){
- tsip_message_add_headers(request,
- TSIP_HEADER_REQUIRE_VA_ARGS("100rel"),
- tsk_null
- );
- }
- else if(self->supported._100rel){
- tsip_message_add_headers(request,
- TSIP_HEADER_SUPPORTED_VA_ARGS("100rel"),
- tsk_null
- );
- }
-
- /* QoS */
- if(self->require.precondition){
- tsip_message_add_headers(request,
- TSIP_HEADER_REQUIRE_VA_ARGS("precondition"),
- tsk_null
- );
- }
- else if(self->supported.precondition){
- tsip_message_add_headers(request,
- TSIP_HEADER_SUPPORTED_VA_ARGS("precondition"),
- tsk_null
- );
- }
-
-
- /* Always added headers */
- // Explicit Communication Transfer (3GPP TS 24.629)
- /*tsip_message_add_headers(request,
- TSIP_HEADER_SUPPORTED_VA_ARGS("norefersub,replaces"),
- tsk_null
- );*/
-
- /* send the request */
- ret = tsip_dialog_request_send(TSIP_DIALOG(self), request);
- if(ret == 0){
- /* update last INVITE */
- TSK_OBJECT_SAFE_FREE(self->last_oInvite);
- self->last_oInvite = request;
- }
- else{
- TSK_OBJECT_SAFE_FREE(request);
- }
- }
-
-bail:
- return ret;
-}
-
-// Send PRACK
-int send_PRACK(tsip_dialog_invite_t *self, const tsip_response_t* r1xx)
-{
- // "Require: 100rel\r\n" should be checked by the caller of this function
- int ret = -1;
- tsip_request_t *request = tsk_null;
- const tsip_header_RSeq_t* RSeq;
-
- if(!self || !r1xx || !r1xx->CSeq){
- TSK_DEBUG_ERROR("Invalid parameter");
- goto bail;
- }
-
-
- /* RFC 3262 - 4 UAC Behavior
- The UAC MUST maintain a sequence number that indicates the most recently
- received in-order reliable provisional response for the initial request.
- */
- if((RSeq = (const tsip_header_RSeq_t*)tsip_message_get_header(r1xx, tsip_htype_RSeq))){
-
- /* RFC 3262 - 4 UAC Behavior
- If the UAC receives another reliable provisional
- response to the same request, and its RSeq value is not one higher
- than the value of the sequence number, that response MUST NOT be
- acknowledged with a PRACK, and MUST NOT be processed further by the
- UAC. An implementation MAY discard the response, or MAY cache the
- response in the hopes of receiving the missing responses.
- */
- if(self->rseq && (RSeq->seq <= self->rseq)){
- TSK_DEBUG_WARN("1xx.RSeq value is not one higher than lastINVITE.RSeq.");
- ret = 0; /* Not error */
- goto bail;
- }
- self->rseq = RSeq->seq;
- }
-
- /* RFC 3262 - 4 UAC Behavior
- Assuming the response is to be transmitted reliably, the UAC MUST
- create a new request with method PRACK.
- */
- if(!(request = tsip_dialog_request_new(TSIP_DIALOG(self), "PRACK"))){
- goto bail;
- }
-
- /* RFC 3262 - 7.2 RAck
- The first number is the value from the RSeq header in the provisional
- response that is being acknowledged. The next number, and the
- method, are copied from the CSeq in the response that is being
- acknowledged. The method name in the RAck header is case sensitive.
- */
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_RACK_VA_ARGS(self->rseq, r1xx->CSeq->seq, r1xx->CSeq->method));
- //TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_DUMMY_VA_ARGS("Test", "value"));
-
- /* Initial INVITE was a bodiless request and 100rel is supported (I'm Alice)
- 1. Alice sends an initial INVITE without offer
- 2. Bob's answer is sent in the first reliable provisional response, in this case it's a 1xx INVITE response
- 3. Alice's answer is sent in the PRACK response
- */
- if(self->is_client && (self->last_oInvite && !TSIP_MESSAGE_HAS_CONTENT(self->last_oInvite))){
- const tsdp_message_t* sdp_lo;
- char* sdp;
- if((sdp_lo = tmedia_session_mgr_get_lo(self->msession_mgr)) && (sdp = tsdp_message_tostring(sdp_lo))){
- tsip_message_add_content(request, "application/sdp", sdp, tsk_strlen(sdp));
- TSK_FREE(sdp);
- }
- }
-
- // Send request
- ret = tsip_dialog_request_send(TSIP_DIALOG(self), request);
-
-bail:
- TSK_OBJECT_SAFE_FREE(request);
- return ret;
-}
-
-// Send CANCEL
-int send_CANCEL(tsip_dialog_invite_t *self)
-{
- int ret = -1;
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- goto bail;
- }
- /* RFC 3261 - 9 Canceling a Request
- If the request being cancelled contains a Route header field, the
- CANCEL request MUST include that Route header field's values.
- ==> up to tsip_dialog_request_new()
- */
-
- /* RFC 3261 - 9 Canceling a Request
- Once the CANCEL is constructed, the client SHOULD check whether it
- has received any response (provisional or final) for the request
- being cancelled (herein referred to as the "original request").
-
- If no provisional response has been received, the CANCEL request MUST
- NOT be sent; rather, the client MUST wait for the arrival of a
- provisional response before sending the request.
- ==> up to the caller to check that we are not in the initial state and the FSM
- is in Trying state.
- */
-
- /* RFC 3261 - 9 Canceling a Request
- The following procedures are used to construct a CANCEL request. The
- Request-URI, Call-ID, To, the numeric part of CSeq, and From header
- fields in the CANCEL request MUST be identical to those in the
- request being cancelled, including tags. A CANCEL constructed by a
- client MUST have only a single Via header field value matching the
- top Via value in the request being cancelled. Using the same values
- for these header fields allows the CANCEL to be matched with the
- request it cancels (Section 9.2 indicates how such matching occurs).
- However, the method part of the CSeq header field MUST have a value
- of CANCEL. This allows it to be identified and processed as a
- transaction in its own right (See Section 17)
- */
- if(self->last_oInvite){
- /* to avoid concurrent access, take a reference to the request */
- tsip_request_t* last_oInvite = tsk_object_ref(self->last_oInvite);
- tsip_request_t* cancel;
-
- if((cancel = tsip_request_create("CANCEL", last_oInvite->line.request.uri))){
- const tsk_list_item_t* item;
- const tsip_header_t* header;
-
- tsip_message_add_headers(cancel,
- TSIP_HEADER_CSEQ_VA_ARGS(last_oInvite->CSeq->seq, "CANCEL"),
- TSIP_HEADER_MAX_FORWARDS_VA_ARGS(TSIP_HEADER_MAX_FORWARDS_DEFAULT),
- TSIP_HEADER_CONTENT_LENGTH_VA_ARGS(0),
- tsk_null);
-
- cancel->Call_ID = tsk_object_ref(last_oInvite->Call_ID);
- cancel->To = tsk_object_ref(last_oInvite->To);
- cancel->From = tsk_object_ref(last_oInvite->From);
- cancel->firstVia = tsk_object_ref(last_oInvite->firstVia);
-
- // Copy Authorizations, Routes and Proxy-Auth
- tsk_list_foreach(item, last_oInvite->headers){
- if(!(header = TSIP_HEADER(item->data))){
- continue;
- }
-
- switch(header->type){
- case tsip_htype_Route:
- case tsip_htype_Proxy_Authorization:
- case tsip_htype_Authorization:
- header = tsk_object_ref((void*)header);
- if(!cancel->headers){
- cancel->headers = tsk_list_create();
- }
- tsk_list_push_back_data(cancel->headers, (void**)&header);
- break;
- }
- }
-
- ret = tsip_dialog_request_send(TSIP_DIALOG(self), cancel);
- TSK_OBJECT_SAFE_FREE(cancel);
- }
- else{
- TSK_DEBUG_ERROR("Failed to create CANCEL request");
- ret = -2;
- }
-
- TSK_OBJECT_SAFE_FREE(last_oInvite);
- return ret;
- }
- else{
- TSK_DEBUG_WARN("There is no INVITE request to cancel");
- return 0;
- }
-
-bail:
- return ret;
-}
-
-// Send BYE
-int send_BYE(tsip_dialog_invite_t *self)
-{
- int ret = -1;
- tsip_request_t *bye = tsk_null;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- goto bail;
- }
- /* RFC 3261 - 15.1.1 UAC Behavior
- A BYE request is constructed as would any other request within a
- dialog, as described in Section 12.
-
- Once the BYE is constructed, the UAC core creates a new non-INVITE
- client transaction, and passes it the BYE request. The UAC MUST
- consider the session terminated (and therefore stop sending or
- listening for media) as soon as the BYE request is passed to the
- client transaction. If the response for the BYE is a 481
- (Call/Transaction Does Not Exist) or a 408 (Request Timeout) or no
-
- response at all is received for the BYE (that is, a timeout is
- returned by the client transaction), the UAC MUST consider the
- session and the dialog terminated.
- */
- if((bye = tsip_dialog_request_new(TSIP_DIALOG(self), "BYE"))){
- ret = tsip_dialog_request_send(TSIP_DIALOG(self), bye);
- TSK_OBJECT_SAFE_FREE(bye);
- }
-
-bail:
- return ret;
-}
-
-// Send ACK
-int send_ACK(tsip_dialog_invite_t *self, const tsip_response_t* r2xxINVITE)
-{
- int ret = -1;
- tsip_request_t *request = tsk_null;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- goto bail;
- }
-
- if((request = tsip_dialog_request_new(TSIP_DIALOG(self), "ACK"))){
-
- /* The initial INVITE sent by us was a bodiless request and we don't support 100rel (We are Alice)
- 1. Alice sends initial INVITE without offer
- 2. Bob's offer is sent in the 2xx INVITE response
- 3. Alice's answer is sent in the ACK request
- */
- if(self->is_client && (self->last_oInvite && !TSIP_MESSAGE_HAS_CONTENT(self->last_oInvite))){
- const tsdp_message_t* sdp_lo;
- char* sdp;
- if((sdp_lo = tmedia_session_mgr_get_lo(self->msession_mgr)) && (sdp = tsdp_message_tostring(sdp_lo))){
- tsip_message_add_content(request, "application/sdp", sdp, tsk_strlen(sdp));
- TSK_FREE(sdp);
- }
-
- // Start media session if not done
- if(!self->msession_mgr->started && (self->msession_mgr->sdp.lo && self->msession_mgr->sdp.ro)){
- /* Set MSRP Callback */
- if((self->msession_mgr->type & tmedia_msrp) == tmedia_msrp){
- tmedia_session_mgr_set_msrp_cb(self->msession_mgr, TSIP_DIALOG_GET_SS(self)->userdata, TSIP_DIALOG_GET_SS(self)->media.msrp.callback);
- }
- ret = tmedia_session_mgr_start(self->msession_mgr);
- }
- }
-
- /* RFC 3261 - 13.2.2.4 2xx Responses
- The UAC core MUST generate an ACK request for each 2xx received from
- the transaction layer. The header fields of the ACK are constructed
- in the same way as for any request sent within a dialog (see Section
- 12) with the exception of the CSeq and the header fields related to
- authentication. The sequence number of the CSeq header field MUST be
- the same as the INVITE being acknowledged, but the CSeq method MUST
- be ACK. The ACK MUST contain the same credentials as the INVITE. If
- the 2xx contains an offer (based on the rules above), the ACK MUST
- carry an answer in its body. If the offer in the 2xx response is not
- acceptable, the UAC core MUST generate a valid answer in the ACK and
- then send a BYE immediately.
- ==> Credentials will be added by tsip_dialog_request_new() because they are
- associated to the dialog itself.
- ==> It's up to us to add/update the CSeq number.
- ==> ACK requests sent here will create new client transactions, which means that
- they will have there own branches. This is not the case for ACK requests sent from
- the transaction layer.
- */
- request->CSeq->seq = r2xxINVITE->CSeq->seq; /* As the 2xx has the same CSeq than the INVITE */
-
- /* RFC 3261 - 13.2.2.4 2xx Responses
- Once the ACK has been constructed, the procedures of [4] are used to
- determine the destination address, port and transport. However, the
- request is passed to the transport layer directly for transmission,
- rather than a client transaction. This is because the UAC core
- handles retransmissions of the ACK, not the transaction layer. The
- ACK MUST be passed to the client transport every time a
- retransmission of the 2xx final response that triggered the ACK
- arrives.
- */
- if(TSIP_DIALOG_GET_STACK(self)->layer_transport){
- ret = tsip_transport_layer_send(TSIP_DIALOG_GET_STACK(self)->layer_transport, tsk_null, request);
- }
- else{
- ret = -1;
- TSK_DEBUG_ERROR("Not Transport layer associated to this stack");
- }
- TSK_OBJECT_SAFE_FREE(request);
- }
-
-bail:
- return ret;
-}
-
-// Send any response
-int send_RESPONSE(tsip_dialog_invite_t *self, const tsip_request_t* request, short code, const char* phrase, tsk_bool_t force_sdp)
-{
- tsip_response_t *response;
- int ret = -1;
-
- if((response = tsip_dialog_response_new(TSIP_DIALOG(self), code, phrase, request))){
- if(TSIP_REQUEST_IS_INVITE(request) || TSIP_REQUEST_IS_UPDATE(request)){
- /* Session timers (for 2xx to INVITE or UPDATE) */
- if(self->stimers.timer.timeout){
- tsip_message_add_headers(response,
- TSIP_HEADER_SUPPORTED_VA_ARGS("timer"),
- TSIP_HEADER_SESSION_EXPIRES_VA_ARGS(self->stimers.timer.timeout, tsk_striequals(self->stimers.refresher, "uas")),
- tsk_null
- );
- }
- if(self->stimers.minse){
- tsip_message_add_headers(response,
- TSIP_HEADER_MIN_SE_VA_ARGS(self->stimers.minse),
- tsk_null
- );
- }
- if(code == 422){
- tsip_message_add_headers(response,
- TSIP_HEADER_DUMMY_VA_ARGS("Reason", "SIP; cause=422; text=\"Session Interval Too Small\""),
- tsk_null
- );
- }
-
- /* 180 Ringing */
- /* 183 Session in Progress */
- if(code == 180 || code == 183){
- if(self->require._100rel){
- tsip_message_add_headers(response,
- TSIP_HEADER_REQUIRE_VA_ARGS("100rel"),
- TSIP_HEADER_RSEQ_VA_ARGS(self->rseq),
- tsk_null
- );
- TSK_OBJECT_SAFE_FREE(self->last_o1xxrel);
- self->last_o1xxrel = tsk_object_ref(response);
-
- /* No-Initial reliable 1xx will use tsip_dialog_response_send() instead of this function
- * ==> can reseset timeout value and make initial schedule */
- TSIP_DIALOG_TIMER_CANCEL(100rel);
- self->timer100rel.timeout = tsip_timers_getA();
- TSIP_DIALOG_INVITE_TIMER_SCHEDULE(100rel);
- }
- }
-
- /* Precondition */
- if(code == 180 || code == 183){
- if(self->require.precondition){
- tsip_message_add_headers(response,
- TSIP_HEADER_REQUIRE_VA_ARGS("precondition"),
- tsk_null
- );
- }
- }
-
-
- /* SDP content */
- if(self->msession_mgr && force_sdp){
- const tsdp_message_t* sdp_lo;
- char* sdp;
- if((sdp_lo = tmedia_session_mgr_get_lo(self->msession_mgr)) && (sdp = tsdp_message_tostring(sdp_lo))){
- tsip_message_add_content(response, "application/sdp", sdp, tsk_strlen(sdp));
- TSK_FREE(sdp);
- }
- }
-
- /* Add Allow header */
- tsip_message_add_headers(response,
- TSIP_HEADER_DUMMY_VA_ARGS("Allow", TSIP_HEADER_ALLOW_DEFAULT),
- tsk_null
- );
- }
-
- ret = tsip_dialog_response_send(TSIP_DIALOG(self), response);
- TSK_OBJECT_SAFE_FREE(response);
- }
- return ret;
-}
-
-// Send error response
-int send_ERROR(tsip_dialog_invite_t* self, const tsip_request_t* request, short code, const char* phrase, const char* reason)
-{
- tsip_response_t *response;
-
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if((response = tsip_dialog_response_new(TSIP_DIALOG(self), code, phrase, request))){
- tsip_message_add_headers(response,
- TSIP_HEADER_DUMMY_VA_ARGS("Reason", reason),
- tsk_null
- );
-
- tsip_dialog_response_send(TSIP_DIALOG(self), response);
- TSK_OBJECT_SAFE_FREE(response);
- }
- else{
- TSK_DEBUG_ERROR("Failed to create new message");
- }
- return 0;
-}
-
-// FSM callback to signal that the dialog is in the terminated state
-int tsip_dialog_invite_OnTerminated(tsip_dialog_invite_t *self)
-{
- TSK_DEBUG_INFO("=== INVITE Dialog terminated ===");
-
- /* stop session manager */
- if(self->msession_mgr && self->msession_mgr->started){
- tmedia_session_mgr_stop(self->msession_mgr);
- }
-
- /* alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminated,
- TSIP_DIALOG(self)->lasterror ? TSIP_DIALOG(self)->lasterror : "Call Terminated");
-
- /* Remove from the dialog layer. */
- return tsip_dialog_remove(TSIP_DIALOG(self));
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-//========================================================
-// SIP dialog INVITE object definition
-//
-static tsk_object_t* tsip_dialog_invite_ctor(tsk_object_t * self, va_list * app)
-{
- tsip_dialog_invite_t *dialog = self;
- if(dialog){
- tsip_ssession_handle_t *ss = va_arg(*app, tsip_ssession_handle_t *);
- const char* call_id = va_arg(*app, const char *);
-
- /* Initialize base class */
- tsip_dialog_init(TSIP_DIALOG(self), tsip_dialog_INVITE, call_id, ss, _fsm_state_Started, _fsm_state_Terminated);
-
- /* FSM */
- TSIP_DIALOG_GET_FSM(dialog)->debug = DEBUG_STATE_MACHINE;
- tsk_fsm_set_callback_terminated(TSIP_DIALOG_GET_FSM(dialog), TSK_FSM_ONTERMINATED_F(tsip_dialog_invite_OnTerminated), (const void*)dialog);
-
- /* Initialize the class itself */
- tsip_dialog_invite_init(self);
- }
- return self;
-}
-
-static tsk_object_t* tsip_dialog_invite_dtor(tsk_object_t * _self)
-{
- tsip_dialog_invite_t *self = _self;
- if(self){
- /* Cancel all timers */
- tsip_dialog_invite_stimers_cancel(self);
- tsip_dialog_invite_qos_timer_cancel(self);
- TSIP_DIALOG_TIMER_CANCEL(shutdown);
- TSIP_DIALOG_TIMER_CANCEL(100rel);
-
- /* DeInitialize base class */
- tsip_dialog_deinit(TSIP_DIALOG(self));
-
- /* DeInitialize self */
- TSK_OBJECT_SAFE_FREE(self->msession_mgr);
- TSK_OBJECT_SAFE_FREE(self->last_oInvite);
- TSK_OBJECT_SAFE_FREE(self->last_iInvite);
- TSK_OBJECT_SAFE_FREE(self->last_o1xxrel);
- TSK_FREE(self->stimers.refresher);
- //...
-
- TSK_DEBUG_INFO("*** INVITE Dialog destroyed ***");
- }
- return self;
-}
-
-static int tsip_dialog_invite_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
-{
- return tsip_dialog_cmp(obj1, obj2);
-}
-
-static const tsk_object_def_t tsip_dialog_invite_def_s =
-{
- sizeof(tsip_dialog_invite_t),
- tsip_dialog_invite_ctor,
- tsip_dialog_invite_dtor,
- tsip_dialog_invite_cmp,
-};
-const tsk_object_def_t *tsip_dialog_invite_def_t = &tsip_dialog_invite_def_s;
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.cdiv.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.cdiv.c
deleted file mode 100644
index e69de29..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.cdiv.c
+++ /dev/null
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.client.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.client.c
deleted file mode 100644
index 768be4c..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.client.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_invite.client.c
- * @brief SIP dialog INVITE as per RFC 3261.
- * The SOA machine is designed as per RFC 3264 and draft-ietf-sipping-sip-offeranswer-12.
- * MMTel services implementation follow 3GPP TS 24.173.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_invite.h"
-
-#include "tinysip/dialogs/tsip_dialog_invite.common.h"
-
-#include "tinysip/headers/tsip_header_Session_Expires.h"
-
-#include "tinysdp/parsers/tsdp_parser_message.h"
-
-#include "tnet_transport.h"
-
-#include "tsk_debug.h"
-
-/* ======================== external functions ======================== */
-extern int send_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE, tsk_bool_t force_sdp);
-extern int send_ACK(tsip_dialog_invite_t *self, const tsip_response_t* r2xxINVITE);
-extern int send_CANCEL(tsip_dialog_invite_t *self);
-extern int tsip_dialog_invite_process_ro(tsip_dialog_invite_t *self, const tsip_message_t* message);
-extern int tsip_dialog_invite_stimers_handle(tsip_dialog_invite_t* self, const tsip_message_t* message);
-
-extern int x0000_Any_2_Any_X_i1xx(va_list *app);
-
-/* ======================== transitions ======================== */
-int c0000_Started_2_Outgoing_X_oINVITE(va_list *app);
-int c0000_Outgoing_2_Connected_X_i2xxINVITE(va_list *app);
-int c0000_Outgoing_2_Terminated_X_i300_to_i699INVITE(va_list *app);
-int c0000_Outgoing_2_Cancelling_X_oCANCEL(va_list *app);
-int c0000_Cancelling_2_Terminated_X_i300_to_699(va_list *app); /* 487 INVITE (To have more chances, any 300-699) */
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_is_resp2INVITE(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return TSIP_RESPONSE_IS_TO_INVITE(message);
-}
-
-static tsk_bool_t _fsm_cond_is_resp2CANCEL(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return TSIP_RESPONSE_IS_TO_CANCEL(message);
-}
-
-/* Init FSM */
-int tsip_dialog_invite_client_init(tsip_dialog_invite_t *self)
-{
- return tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Started ===
- */
- // Started -> (send INVITE) -> Outgoing
- TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_oINVITE, _fsm_state_Outgoing, c0000_Started_2_Outgoing_X_oINVITE, "c0000_Started_2_Outgoing_X_oINVITE"),
-
- /*=======================
- * === Outgoing ===
- */
- // Outgoing -> (i2xx INVITE) -> Connected
- TSK_FSM_ADD(_fsm_state_Outgoing, _fsm_action_i2xx, _fsm_cond_is_resp2INVITE, _fsm_state_Connected, c0000_Outgoing_2_Connected_X_i2xxINVITE, "c0000_Outgoing_2_Connected_X_i2xxINVITE"),
- // Outgoing -> (oCANCEL) -> Cancelling
- TSK_FSM_ADD_ALWAYS(_fsm_state_Outgoing, _fsm_action_oCANCEL, _fsm_state_Cancelling, c0000_Outgoing_2_Cancelling_X_oCANCEL, "c0000_Outgoing_2_Cancelling_X_oCANCEL"),
- // Cancelling -> (any response to cancel CANCEL) -> Cancelling
- TSK_FSM_ADD(_fsm_state_Cancelling, _fsm_action_i300_to_i699, _fsm_cond_is_resp2CANCEL, _fsm_state_Terminated, tsk_null, "c0000_Cancelling_2_Terminated_X_i300_to_699"),
- TSK_FSM_ADD(_fsm_state_Cancelling, _fsm_action_i2xx, _fsm_cond_is_resp2CANCEL, _fsm_state_Cancelling, tsk_null, "c0000_Cancelling_2_Cancelling_X_i2xx"),
- // Cancelling -> (i300-699 INVITE) -> Terminated
- TSK_FSM_ADD(_fsm_state_Cancelling, _fsm_action_i300_to_i699, _fsm_cond_is_resp2INVITE, _fsm_state_Terminated, c0000_Cancelling_2_Terminated_X_i300_to_699, "c0000_Cancelling_2_Terminated_X_i300_to_699"),
- // Outgoing -> (300-699 INVITE) -> Terminated
- TSK_FSM_ADD(_fsm_state_Outgoing, _fsm_action_i300_to_i699, _fsm_cond_is_resp2INVITE, _fsm_state_Terminated, c0000_Outgoing_2_Terminated_X_i300_to_i699INVITE, "c0000_Outgoing_2_Terminated_X_i300_to_i699INVITE"),
-
- TSK_FSM_ADD_NULL());
-}
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-/* Started -> (oINVITE) -> Outgoing
-*/
-int c0000_Started_2_Outgoing_X_oINVITE(va_list *app)
-{
- int ret;
- tsip_dialog_invite_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_invite_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* This is the first FSM transaction when you try to make an audio/video/msrp call */
- if(!self->msession_mgr){
- self->msession_mgr = tmedia_session_mgr_create(action ? action->media.type : tmedia_all,
- TSIP_DIALOG_GET_STACK(self)->network.local_ip, TNET_SOCKET_TYPE_IS_IPV6(TSIP_DIALOG_GET_STACK(self)->network.proxy_cscf_type), tsk_true);
- if(TSIP_DIALOG_GET_STACK(self)->natt.ctx){
- tmedia_session_mgr_set_natt_ctx(self->msession_mgr, TSIP_DIALOG_GET_STACK(self)->natt.ctx, TSIP_DIALOG_GET_STACK(self)->network.aor.ip);
- }
- }
-
- /* We are the client */
- self->is_client = tsk_true;
-
- /* Update current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* Get Media type from the action */
- TSIP_DIALOG_GET_SS(self)->media.type = action->media.type;
- /* Appy media params received from the user */
- if(!TSK_LIST_IS_EMPTY(action->media.params)){
- tmedia_session_mgr_set_3(self->msession_mgr, action->media.params);
- }
-
- /* RFC 4028 - 7.1. Generating an Initial Session Refresh Request
-
- A UAC MAY include a Session-Expires header field in an initial
- session refresh request if it wants a session timer applied to the
- session. The value of this header field indicates the session
- interval desired by the UAC. If a Min-SE header is included in the
- initial session refresh request, the value of the Session-Expires
- MUST be greater than or equal to the value in Min-SE.
-
- The UAC MAY include the refresher parameter with value 'uac' if it
- wants to perform the refreshes. However, it is RECOMMENDED that the
- parameter be omitted so that it can be selected by the negotiation
- mechanisms described below.
- */
- if(TSIP_DIALOG_GET_SS(self)->media.timers.timeout){
- self->stimers.timer.timeout = TSIP_DIALOG_GET_SS(self)->media.timers.timeout;
- tsk_strupdate(&self->stimers.refresher, TSIP_DIALOG_GET_SS(self)->media.timers.refresher);
- self->supported.timer = tsk_true;
- }
-
- /* QoS
- * One Voice Profile - 5.4.1 SIP Precondition Considerations
- * The UE shall use the Supported header, and not the Require header, to indicate the support of precondition in
- * accordance with Section 5.1.3.1 of 3GPP TS 24.229.
- */
- self->qos.type = TSIP_DIALOG_GET_SS(self)->media.qos.type;
- self->qos.strength = TSIP_DIALOG_GET_SS(self)->media.qos.strength;
- tmedia_session_mgr_set_qos(self->msession_mgr, self->qos.type, self->qos.strength);
- self->supported.precondition = (self->qos.strength == tmedia_qos_strength_optional);
- self->require.precondition = (self->qos.strength == tmedia_qos_strength_mandatory);
-
- /* 100rel */
- self->supported._100rel = TSIP_DIALOG_GET_SS(self)->media.enable_100rel;
-
- /* send the request */
- ret = send_INVITE(self, tsk_false);
-
- /* alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connecting, "Dialog connecting");
-
- return ret;
-}
-
-/* Outgoing -> (i2xx INVITE) -> Connected
-*/
-int c0000_Outgoing_2_Connected_X_i2xxINVITE(va_list *app)
-{
- int ret;
-
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_response_t *r2xxINVITE = va_arg(*app, const tsip_response_t *);
- const tsip_action_t* action = va_arg(*app, const tsip_action_t *);
-
- /* Update the dialog state */
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), r2xxINVITE))){
- return ret;
- }
-
- /* Process remote offer */
- if((ret = tsip_dialog_invite_process_ro(self, r2xxINVITE))){
- /* Send error */
- return ret;
- }
- else{
- /* send ACK */
- ret = send_ACK(self, r2xxINVITE);
- }
-
- /* Determine whether the remote party support UPDATE */
- self->support_update = tsip_message_allowed(r2xxINVITE, "UPDATE");
-
- /* Session Timers */
- if(self->stimers.timer.timeout){
- tsip_dialog_invite_stimers_handle(self, r2xxINVITE);
- }
-
- /* Alert the user (session) */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_ao_request,
- TSIP_RESPONSE_CODE(r2xxINVITE), TSIP_RESPONSE_PHRASE(r2xxINVITE), r2xxINVITE);
- /* Alert the user (dialog) */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connected, "Dialog connected");
-
- /* MSRP File Transfer */
- /*if(TSIP_DIALOG(self)->curr_action && ((TSIP_DIALOG(self)->curr_action->media.type & tmedia_msrp) == tmedia_msrp)){
- // FIXME
- tmedia_session_mgr_send_file(self->msession_mgr, "C:\\avatar.png",
- TMEDIA_SESSION_SET_NULL());
- }*/
-
- return ret;
-}
-
-/* Outgoing -> (i300-i699 INVITE) -> Terminated
-*/
-int c0000_Outgoing_2_Terminated_X_i300_to_i699INVITE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), TSIP_RESPONSE_PHRASE(response));
-
- /* alert the user */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_ao_request,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return 0;
-}
-
-/* Outgoing -> (oCANCEL ) -> Cancelling
-*/
-int c0000_Outgoing_2_Cancelling_X_oCANCEL(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminating, "Terminating dialog");
-
- return send_CANCEL(self);
-}
-
-int c0000_Cancelling_2_Terminated_X_i300_to_699(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), "Request cancelled");
-
- return 0;
-}
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++ \ No newline at end of file
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.conf.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.conf.c
deleted file mode 100644
index 4ced2f8..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.conf.c
+++ /dev/null
@@ -1 +0,0 @@
-//http://www.quintillion.co.jp/3GPP/Specs/24147-900.pdf \ No newline at end of file
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.ect.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.ect.c
deleted file mode 100644
index 34ecd2f..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.ect.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_invite.hold.c
- * @brief Explicit Communication Transfer (ECT) using IP Multimedia (IM) Core Network (CN) subsystem (3GPP TS 24.629)
- * The Explicit Communication transfer (ECT) service provides a party involved in a communication to transfer that
- * communication to a third party.
- * Only Consultative transfer is supportted (A2). Blind transfer (A1) will be added later.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_invite.h"
-
-#include "tinysip/dialogs/tsip_dialog_invite.common.h"
-
-#include "tinysip/headers/tsip_header_Refer_To.h"
-#include "tinysip/headers/tsip_header_Supported.h"
-
-#include "tinysip/parsers/tsip_parser_uri.h"
-
-#include "tsk_debug.h"
-
-/* ======================== transitions ======================== */
-static int x0400_Connected_2_oECTing_X_oREFER(va_list *app);
-static int x0401_oECTing_2_oECTed_X_i2xx(va_list *app); // should be 202?
-static int x0402_oECTing_2_Connected_X_i300_to_699(va_list *app);
-static int x0401_oECTed_2_oECTed_X_iNOTIFY(va_list *app); // Notify 1xx
-static int x0401_oECTed_2_Connected_X_iNOTIFY(va_list *app); // Notify 200_to_699
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_is_resp2REFER(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return TSIP_RESPONSE_IS_TO_REFER(message);
-}
-
-
-int tsip_dialog_invite_ect_init(tsip_dialog_invite_t *self)
-{
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Outgoing Transfer ===
- */
- // Connected -> (send REFER) -> ECTing
- // ECTing -> (i2xx) -> ECTed
- // ECTing -> (i300-699) -> Connected
- // ECTed -> (iNotify 1xx) -> ECTed
- // ECTed -> (iNotify non-1xx) -> Connected
-
-
- /*=======================
- * === Incoming Transfer ===
- */
-
- TSK_FSM_ADD_NULL());
-
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-int send_REFER(tsip_dialog_invite_t *self, const char* to)
-{
- int ret = 0;
- tsip_request_t *refer = tsk_null;
- tsip_uri_t* toUri = tsk_null;
-
- if(!self || !to){
- TSK_DEBUG_ERROR("Invalid parameter");
- goto bail;
- }
-
- if(!(toUri = tsip_uri_parse(to, tsk_strlen(to)))){
- TSK_DEBUG_ERROR("Failed to parse %s", to);
- goto bail;
- }
- else{
- tsk_params_add_param(&toUri->params, "method", "INVITE");
- }
-
- if((refer = tsip_dialog_request_new(TSIP_DIALOG(self), "REFER"))){
- /* Add headers */
- tsip_message_add_headers(refer,
- TSIP_HEADER_REFER_TO_VA_ARGS(toUri),
- TSIP_HEADER_SUPPORTED_VA_ARGS("norefersub"),
- tsk_null);
-
- ret = tsip_dialog_request_send(TSIP_DIALOG(self), refer);
- TSK_OBJECT_SAFE_FREE(refer);
- }
-
-bail:
- TSK_OBJECT_SAFE_FREE(toUri);
- return ret;
-}
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.hold.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.hold.c
deleted file mode 100644
index 79ab817..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.hold.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_invite.hold.c
- * @brief Communication Hold (3GPP TS 24.610)
- * The Communication Hold supplementary service enables a user to suspend the reception of media stream(s) of an established IP multimedia session,
- * and resume the media stream(s) at a later time.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_invite.h"
-
-#include "tinysip/dialogs/tsip_dialog_invite.common.h"
-
-#include "tsk_debug.h"
-
-/* ======================== transitions ======================== */
-static int x0100_Connected_2_Holding_X_oHold(va_list *app);
-static int x0101_Holding_2_Connected_X_ixxx(va_list *app);
-static int x0102_Connected_2_Resuming_X_oResume(va_list *app);
-static int x0103_Resuming_2_Connected_X_ixxx(va_list *app);
-
-static int x0150_Any_2_Any_X_i422(va_list *app);
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_is_resp2INVITEorUPDATE(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return (TSIP_RESPONSE_IS_TO_INVITE(message) || TSIP_RESPONSE_IS_TO_UPDATE(message));
-}
-
-/* ======================== external functions ======================== */
-extern int send_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE, tsk_bool_t force_sdp);
-extern int tsip_dialog_invite_process_ro(tsip_dialog_invite_t *self, const tsip_message_t* message);
-extern int send_ACK(tsip_dialog_invite_t *self, const tsip_response_t* r2xxINVITE);
-
-int tsip_dialog_invite_hold_init(tsip_dialog_invite_t *self)
-{
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Hold ===
- */
- // Connected -> (send HOLD) -> Holding
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_oHold, _fsm_state_Holding, x0100_Connected_2_Holding_X_oHold, "x0100_Connected_2_Holding_X_oHold"),
- // Holding -> (i2xx) -> Connected
- TSK_FSM_ADD(_fsm_state_Holding, _fsm_action_i2xx, _fsm_cond_is_resp2INVITEorUPDATE, _fsm_state_Connected, x0101_Holding_2_Connected_X_ixxx, "x0101_Holding_2_Connected_X_ixxx"),
- // Holding -> (i300-699) -> Connected
- TSK_FSM_ADD(_fsm_state_Holding, _fsm_action_i300_to_i699, _fsm_cond_is_resp2INVITEorUPDATE, _fsm_state_Connected, x0101_Holding_2_Connected_X_ixxx, "x0101_Holding_2_Connected_X_ixxx"),
-
- /*=======================
- * === Resume ===
- */
- // Connected -> (send RESUME) -> Resuming
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_oResume, _fsm_state_Resuming, x0102_Connected_2_Resuming_X_oResume, "x0102_Connected_2_Resuming_X_oResume"),
- // Resuming -> (i2xx) -> Connected
- TSK_FSM_ADD(_fsm_state_Resuming, _fsm_action_i2xx, _fsm_cond_is_resp2INVITEorUPDATE, _fsm_state_Connected, x0103_Resuming_2_Connected_X_ixxx, "x0103_Resuming_2_Connected_X_ixxx"),
- // Resuming -> (i300-699) -> Connected
- TSK_FSM_ADD(_fsm_state_Resuming, _fsm_action_i300_to_i699, _fsm_cond_is_resp2INVITEorUPDATE, _fsm_state_Connected, x0103_Resuming_2_Connected_X_ixxx, "x0103_Resuming_2_Connected_X_ixxx"),
-
- TSK_FSM_ADD_NULL());
-
- return 0;
-}
-
-
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-// Connected -> (send HOLD) -> Holding
-int x0100_Connected_2_Holding_X_oHold(va_list *app)
-{
- int ret;
- tsip_dialog_invite_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_invite_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- if(!self->msession_mgr){
- TSK_DEBUG_WARN("Media Session manager is Null");
- return 0;
- }
-
- /* put on hold */
- ret = tmedia_session_mgr_hold(self->msession_mgr, action->media.type);
-
- /* update current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* send the request */
- if((ret = send_INVITE(self, tsk_false))){
- // FIXME: signal error without breaking the state machine
- }
-
- return 0;
-}
-
-// Holding -> (ixxx) -> Connected
-int x0101_Holding_2_Connected_X_ixxx(va_list *app)
-{
- int ret;
-
- tsip_dialog_invite_t* self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_response_t* response = va_arg(*app, const tsip_response_t *);
-
- /* reset current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), tsk_null);
-
- /* Process remote offer */
- if((ret = tsip_dialog_invite_process_ro(self, response))){
- /* Send error */
- return ret;
- }
- else if(TSIP_RESPONSE_IS_TO_INVITE(response)){
- /* send ACK */
- ret = send_ACK(self, response);
- }
-
- /* alert the user */
- if(TSIP_RESPONSE_IS_2XX(response)){
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_m_local_hold_ok,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- self->hold.local = tsk_true;
- }
- else{
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_m_local_hold_nok,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- self->hold.local = tsk_false;
- }
-
- return ret;
-}
-
-// Connected -> (send RESUME) -> Resuming
-int x0102_Connected_2_Resuming_X_oResume(va_list *app)
-{
- int ret;
- tsip_dialog_invite_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_invite_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- if(!self->msession_mgr){
- TSK_DEBUG_WARN("Media Session manager is Null");
- return 0;
- }
-
- /* Resume */
- ret = tmedia_session_mgr_resume(self->msession_mgr, action->media.type);
-
- /* update current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* send the request */
- if((ret = send_INVITE(self, tsk_false))){
- // FIXME: signal error without breaking the state machine
- }
-
- return 0;
-}
-
-// Resuming -> (ixxx) -> Connected
-int x0103_Resuming_2_Connected_X_ixxx(va_list *app)
-{
- int ret;
-
- tsip_dialog_invite_t* self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_response_t* response = va_arg(*app, const tsip_response_t *);
-
- /* reset current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), tsk_null);
-
- /* Process remote offer */
- if((ret = tsip_dialog_invite_process_ro(self, response))){
- /* Send error */
- return ret;
- }
- else if(TSIP_RESPONSE_IS_TO_INVITE(response)){
- /* send ACK */
- ret = send_ACK(self, response);
- }
-
- /* alert the user */
- if(TSIP_RESPONSE_IS_2XX(response)){
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_m_local_resume_ok,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- self->hold.local = tsk_false;
- }
- else{
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_m_local_resume_nok,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- self->hold.local = tsk_true;
- }
-
- return ret;
-}
-
-/* handle requests/responses (MUST be called after set_ro()) */
-int tsip_dialog_invite_hold_handle(tsip_dialog_invite_t* self, const tsip_request_t* rINVITEorUPDATE)
-{
- tsk_bool_t remote_hold;
-
- if(!self || !rINVITEorUPDATE || !self->msession_mgr){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- remote_hold = tmedia_session_mgr_is_held(self->msession_mgr, self->msession_mgr->type, tsk_false);
-
- if(remote_hold != self->hold.remote){
- self->hold.remote = remote_hold;
- TSIP_DIALOG_INVITE_SIGNAL(self, self->hold.remote ? tsip_m_remote_hold : tsip_m_remote_resume,
- tsip_event_code_dialog_request_incoming, "Hold/Resume state changed", rINVITEorUPDATE);
- }
-
- return 0;
-}
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.qos.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.qos.c
deleted file mode 100644
index 2871011..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.qos.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_invite.qos.c
- * @brief Integration of Resource Management and Session Initiation Protocol (SIP) (RFC 3312)
- * QoS Reservation.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_invite.h"
-
-#include "tinysip/dialogs/tsip_dialog_invite.common.h"
-
-#include "tsk_debug.h"
-
-#define TSIP_DIALOG_INVITE_QOS_RES_TIMEOUT 20
-
-/* ======================== external functions ======================== */
-extern int tsip_dialog_invite_timer_callback(const tsip_dialog_invite_t* self, tsk_timer_id_t timer_id);
-extern int send_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE, tsk_bool_t force_sdp);
-
-/* ======================== transitions ======================== */
-static int x0300_Any_2_Any_X_timerRSVP(va_list *app);
-
-/* Init FSM */
-int tsip_dialog_invite_qos_init(tsip_dialog_invite_t *self)
-{
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- // Any -> (timerRSVP) -> Any
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_timerRSVP, tsk_fsm_state_any, x0300_Any_2_Any_X_timerRSVP, "x0300_Any_2_Any_X_timerRSVP"),
-
-
- TSK_FSM_ADD_NULL());
-
- return 0;
-}
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-// Any -> (tiner RSVP) -> Any
-int x0300_Any_2_Any_X_timerRSVP(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- return send_UPDATE(self, tsk_true);
-}
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-
-
-
-/* cancel the timer */
-int tsip_dialog_invite_qos_timer_cancel(tsip_dialog_invite_t* self)
-{
- return tsk_timer_mgr_global_cancel(self->qos.timer.id);
-}
-
-/* schedule the timer */
-int tsip_dialog_invite_qos_timer_schedule(tsip_dialog_invite_t* self)
-{
- /* To emulate bandwidth reservation (Because RSVP protocol is not supported) */
- self->qos.timer.id = tsk_timer_mgr_global_schedule(TSIP_DIALOG_INVITE_QOS_RES_TIMEOUT, TSK_TIMER_CALLBACK_F(tsip_dialog_invite_timer_callback), self);
-
- return 0;
-}
-
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.server.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.server.c
deleted file mode 100644
index 1f15524..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.server.c
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_invite.client.c
- * @brief SIP dialog INVITE as per RFC 3261.
- * The SOA machine is designed as per RFC 3264 and draft-ietf-sipping-sip-offeranswer-12.
- * MMTel services implementation follow 3GPP TS 24.173.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_invite.h"
-
-#include "tinysip/dialogs/tsip_dialog_invite.common.h"
-
-#include "tinysip/transports/tsip_transport_layer.h"
-
-#include "tinysip/headers/tsip_header_Dummy.h"
-#include "tinysip/headers/tsip_header_Min_SE.h"
-#include "tinysip/headers/tsip_header_RAck.h"
-#include "tinysip/headers/tsip_header_Require.h"
-#include "tinysip/headers/tsip_header_Session_Expires.h"
-
-#include "tsk_debug.h"
-
-static const char* supported_options[] = { "100rel", "precondition", "timer" };
-
-/* ======================== external functions ======================== */
-extern int send_RESPONSE(tsip_dialog_invite_t *self, const tsip_request_t* request, short code, const char* phrase, tsk_bool_t force_sdp);
-extern int tsip_dialog_invite_process_ro(tsip_dialog_invite_t *self, const tsip_message_t* message);
-extern int tsip_dialog_invite_stimers_schedule(tsip_dialog_invite_t* self, uint64_t timeout);
-extern tsk_bool_t tsip_dialog_invite_stimers_isRefresher(tsip_dialog_invite_t* self);
-extern int send_ERROR(tsip_dialog_invite_t* self, const tsip_request_t* request, short code, const char* phrase, const char* reason);
-
-extern int tsip_dialog_invite_timer_callback(const tsip_dialog_invite_t* self, tsk_timer_id_t timer_id);
-
-/* ======================== internal functions ======================== */
-int send_UNSUPPORTED(tsip_dialog_invite_t* self, const tsip_request_t* request, const char* option);
-
-/* ======================== transitions ======================== */
-int s0000_Started_2_Terminated_X_iINVITE(va_list *app); // Failure
-int s0000_Started_2_Started_X_iINVITE(va_list *app); // Session Interval Too Small
-int s0000_Started_2_InProgress_X_iINVITE(va_list *app); // 100rel supported
-int s0000_Started_2_Ringing_X_iINVITE(va_list *app); // Neither 100rel nor QoS
-int s0000_InProgress_2_InProgress_X_iPRACK(va_list *app); // PRACK for our 18x response (with QoS)
-int s0000_InProgress_2_Ringing_X_iPRACK(va_list *app); // PRACK for our 18x response (without QoS)
-int s0000_InProgress_2_InProgress_X_iUPDATE(va_list *app); // QoS cannot resume
-int s0000_InProgress_2_Ringing_X_iUPDATE(va_list *app); // QoS can resume (do not alert user, wait for PRACK)
-int s0000_Inprogress_2_Terminated_X_iCANCEL(va_list *app);
-int s0000_Ringing_2_Ringing_X_iPRACK(va_list *app); // Alert user
-int s0000_Ringing_2_Connected_X_Accept(va_list *app);
-int s0000_Ringing_2_Terminated_X_Reject(va_list *app);
-int s0000_Ringing_2_Terminated_X_iCANCEL(va_list *app);
-int s0000_Any_2_Any_X_timer100rel(va_list *app);
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_bad_extension(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- const tsip_header_Require_t* requireHdr;
- const tsk_list_item_t* item;
- tsk_size_t i, j;
-
- /* Check if we support all extensions */
- for(i = 0; (requireHdr = (const tsip_header_Require_t*)tsip_message_get_headerAt(message, tsip_htype_Require, i)); i++){
- tsk_bool_t bad_extension = tsk_false;
- const tsk_string_t* option = tsk_null;
- tsk_list_foreach(item, requireHdr->options){
- option = item->data;
- bad_extension = tsk_true;
- for(j = 0; option && j<sizeof(supported_options)/sizeof(const char*); j++){
- if(tsk_striequals(option->value, supported_options[j])){
- bad_extension = tsk_false;
- break;
- }
- }
- if(bad_extension){
- break;
- }
- }
- if(bad_extension && option){
- send_UNSUPPORTED(self, message, option->value);
- return tsk_true;
- }
- }
-
-
- return tsk_false;
-}
-
-static tsk_bool_t _fsm_cond_bad_content(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- int ret;
- const tsdp_message_t* sdp_lo;
- tsk_bool_t bodiless_INVITE = (TSIP_DIALOG(self)->state == tsip_initial && !TSIP_MESSAGE_HAS_CONTENT(message)); // Initial Bodiless INVITE
-
- /* Check remote offer */
- if((ret = tsip_dialog_invite_process_ro(self, message))){
- ret = send_ERROR(self, message, 488, "Not Acceptable", "SIP; cause=488; text=\"Bad content\"");
- return tsk_true;
- }
- /* generate local offer and check it's validity */
- if(self->msession_mgr && (sdp_lo = tmedia_session_mgr_get_lo(self->msession_mgr))){
- /* check that we have at least one valid session (Only if no bodiless initial INVITE) */
- if(!bodiless_INVITE && !tmedia_session_mgr_has_active_session(self->msession_mgr)){
- ret = send_ERROR(self, message, 488, "Not Acceptable", "SIP; cause=488; text=\"No common codecs\"");
- return tsk_true;
- }
- }
- else{
- ret = send_ERROR(self, message, 488, "Not Acceptable", "SIP; cause=488; text=\"Bad content\"");
- return tsk_true;
- }
-
- return tsk_false;
-}
-
-static tsk_bool_t _fsm_cond_toosmall(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- if(tsip_message_supported(message, "timer") || tsip_message_required(message, "timer")){
- const tsip_header_Session_Expires_t* Session_Expires;
- if((Session_Expires = (const tsip_header_Session_Expires_t*)tsip_message_get_header(message, tsip_htype_Session_Expires))){
- if(Session_Expires->delta_seconds < TSIP_SESSION_EXPIRES_MIN_VALUE){
- self->stimers.minse = TSIP_SESSION_EXPIRES_MIN_VALUE;
- send_RESPONSE(self, message, 422, "Session Interval Too Small", tsk_false);
- return tsk_true;
- }
- else{
- const tsip_header_Min_SE_t* Min_SE;
- self->stimers.timer.timeout = Session_Expires->delta_seconds;
- tsk_strupdate(&self->stimers.refresher, Session_Expires->refresher_uas ? "uas" : "uac");
- if((Min_SE = (const tsip_header_Min_SE_t*)tsip_message_get_header(message, tsip_htype_Min_SE))){
- self->stimers.minse = Min_SE->delta_seconds;
- }
- }
- }
- }
- return tsk_false;
-}
-static tsk_bool_t _fsm_cond_supports_100rel(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- if(tsip_message_supported(message, "100rel") || tsip_message_required(message, "100rel")){
- return tsk_true;
- }
- return tsk_false;
-}
-static tsk_bool_t _fsm_cond_prack_match(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- const tsip_header_RAck_t* RAck;
-
- if(!self->last_o1xxrel){
- return tsk_false;
- }
-
- if((RAck = (const tsip_header_RAck_t*)tsip_message_get_header(message, tsip_htype_RAck))){
- if((RAck->seq == self->rseq) &&
- (tsk_striequals(RAck->method, self->last_o1xxrel->CSeq->method)) &&
- (RAck->cseq == self->last_o1xxrel->CSeq->seq)){
- self->rseq++;
- return tsk_true;
- }
- else{
- TSK_DEBUG_WARN("Failed to match PRACK request");
- }
- }
-
- return tsk_false;
-}
-static tsk_bool_t _fsm_cond_negociates_preconditions(tsip_dialog_invite_t* self, tsip_message_t* rPRACK)
-{
- //tsip_message_supported(self->last_iInvite, "precondition") || tsip_message_required(self->last_iInvite, "precondition")
- if(tsip_message_required(self->last_iInvite, "precondition") || (self->msession_mgr && self->msession_mgr->qos.type == tmedia_qos_strength_mandatory)){
- return tsk_true;
- }
- return tsk_false;
-}
-static tsk_bool_t _fsm_cond_cannotresume(tsip_dialog_invite_t* self, tsip_message_t* rUPDATE)
-{
- if(!tsip_dialog_invite_process_ro(self, rUPDATE)){
- return !tmedia_session_mgr_canresume(self->msession_mgr);
- }
- else{
- return tsk_false;
- }
-}
-
-/* Init FSM */
-int tsip_dialog_invite_server_init(tsip_dialog_invite_t *self)
-{
- return tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Started ===
- */
- // Started -> (Bad Extendion) -> Terminated
- TSK_FSM_ADD(_fsm_state_Started, _fsm_action_iINVITE, _fsm_cond_bad_extension, _fsm_state_Terminated, s0000_Started_2_Terminated_X_iINVITE, "s0000_Started_2_Terminated_X_iINVITE"),
- // Started -> (Bad content) -> Terminated
- TSK_FSM_ADD(_fsm_state_Started, _fsm_action_iINVITE, _fsm_cond_bad_content, _fsm_state_Terminated, s0000_Started_2_Terminated_X_iINVITE, "s0000_Started_2_Terminated_X_iINVITE"),
- // Started -> (Session Interval Too Small) -> Started
- TSK_FSM_ADD(_fsm_state_Started, _fsm_action_iINVITE, _fsm_cond_toosmall, _fsm_state_Started, s0000_Started_2_Started_X_iINVITE, "s0000_Started_2_Started_X_iINVITE"),
- // Started -> (100rel or QoS, the later need the first) -> InProgress
- TSK_FSM_ADD(_fsm_state_Started, _fsm_action_iINVITE, _fsm_cond_supports_100rel, _fsm_state_InProgress, s0000_Started_2_InProgress_X_iINVITE, "s0000_Started_2_InProgress_X_iINVITE"),
- // Started -> (non-100rel and non-QoS, referred to as "basic") -> Ringing
- TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_iINVITE, _fsm_state_Ringing, s0000_Started_2_Ringing_X_iINVITE, "s0000_Started_2_Ringing_X_iINVITE"),
-
-
- /*=======================
- * === InProgress ===
- */
- // InProgress ->(iPRACK with QoS) -> InProgress
- TSK_FSM_ADD(_fsm_state_InProgress, _fsm_action_iPRACK, _fsm_cond_negociates_preconditions, _fsm_state_InProgress, s0000_InProgress_2_InProgress_X_iPRACK, "s0000_InProgress_2_InProgress_X_iPRACK"),
- // InProgress ->(iPRACK without QoS) -> Ringing
- TSK_FSM_ADD(_fsm_state_InProgress, _fsm_action_iPRACK, _fsm_cond_prack_match, _fsm_state_Ringing, s0000_InProgress_2_Ringing_X_iPRACK, "s0000_InProgress_2_Ringing_X_iPRACK"),
- // InProgress ->(iUPDATE but cannot resume) -> InProgress
- TSK_FSM_ADD(_fsm_state_InProgress, _fsm_action_iUPDATE, _fsm_cond_cannotresume, _fsm_state_InProgress, s0000_InProgress_2_InProgress_X_iUPDATE, "s0000_InProgress_2_InProgress_X_iUPDATE"),
- // InProgress ->(iUPDATE can resume) -> Ringing
- TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_iUPDATE, _fsm_state_Ringing, s0000_InProgress_2_Ringing_X_iUPDATE, "s0000_InProgress_2_Ringing_X_iUPDATE"),
- // InProgress ->(iCANCEL) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_iCANCEL, _fsm_state_Terminated, s0000_Inprogress_2_Terminated_X_iCANCEL, "s0000_Inprogress_2_Terminated_X_iCANCEL"),
-
-
- /*=======================
- * === Ringing ===
- */
- // Ringing -> (iPRACK) -> Ringing
- TSK_FSM_ADD(_fsm_state_Ringing, _fsm_action_iPRACK, _fsm_cond_prack_match, _fsm_state_Ringing, s0000_Ringing_2_Ringing_X_iPRACK, "s0000_Ringing_2_Ringing_X_iPRACK"),
- // Ringing -> (oAccept) -> Connected
- TSK_FSM_ADD_ALWAYS(_fsm_state_Ringing, _fsm_action_accept, _fsm_state_Connected, s0000_Ringing_2_Connected_X_Accept, "s0000_Ringing_2_Connected_X_Accept"),
- // Ringing -> (oReject) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Ringing, _fsm_action_reject, _fsm_state_Terminated, s0000_Ringing_2_Terminated_X_Reject, "s0000_Ringing_2_Terminated_X_Reject"),
- // Ringing ->(iCANCEL) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Ringing, _fsm_action_iCANCEL, _fsm_state_Terminated, s0000_Ringing_2_Terminated_X_iCANCEL, "s0000_Ringing_2_Terminated_X_iCANCEL"),
-
- /*=======================
- * === ANY ===
- */
- // Any ->(timer100rel) -> Any
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_timer100rel, tsk_fsm_state_any, s0000_Any_2_Any_X_timer100rel, "s0000_Any_2_Any_X_timer100rel"),
-
-
- TSK_FSM_ADD_NULL());
-}
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-
-/* Started -> (Failure) -> Terminated */
-int s0000_Started_2_Terminated_X_iINVITE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- /* We are not the client */
- self->is_client = tsk_false;
-
- return 0;
-}
-
-/* Started -> (Too Small) -> Started */
-int s0000_Started_2_Started_X_iINVITE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
-
- /* We are not the client */
- self->is_client = tsk_false;
-
- return 0;
-}
-
-/* Started -> (non-100rel and non-QoS, referred to as "basic") -> Ringing */
-int s0000_Started_2_Ringing_X_iINVITE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- /* we are not the client */
- self->is_client = tsk_false;
-
- /* update last INVITE */
- TSK_OBJECT_SAFE_FREE(self->last_iInvite);
- self->last_iInvite = tsk_object_ref(request);
-
- /* update state */
- tsip_dialog_update_2(TSIP_DIALOG(self), request);
-
- /* send Ringing */
- send_RESPONSE(self, request, 180, "Ringing", tsk_false);
-
- /* alert the user (session) */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_i_newcall,
- tsip_event_code_dialog_request_incoming, "Incoming Call", request);
-
- return 0;
-}
-
-/* Started -> (100rel or QoS, the later need the first) -> InProgress */
-int s0000_Started_2_InProgress_X_iINVITE(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- /* We are not the client */
- self->is_client = tsk_false;
-
- /* update last INVITE */
- TSK_OBJECT_SAFE_FREE(self->last_iInvite);
- self->last_iInvite = tsk_object_ref(request);
-
- /* Update state */
- tsip_dialog_update_2(TSIP_DIALOG(self), request);
-
- /* Send In Progress
- RFC 3262 - 3 UAS Behavior
-
- The provisional response to be sent reliably is constructed by the
- UAS core according to the procedures of Section 8.2.6 of RFC 3261.
- In addition, it MUST contain a Require header field containing the
- option tag 100rel, and MUST include an RSeq header field. The value
- of the header field for the first reliable provisional response in a
- transaction MUST be between 1 and 2**31 - 1.
- */
- self->rseq = (rand() ^ rand()) % (0x00000001 << 31);
- self->require._100rel = tsk_true;
- self->require.precondition = (tsip_message_supported(self->last_iInvite, "precondition") || tsip_message_required(self->last_iInvite, "precondition"));
- send_RESPONSE(self, request, 183, "Session in Progress", tsk_true);
-
- return 0;
-}
-
-/* InProgress ->(iPRACK with QoS) -> InProgress */
-int s0000_InProgress_2_InProgress_X_iPRACK(va_list *app)
-{
- int ret;
-
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- /* Cancel 100rel timer */
- TSIP_DIALOG_TIMER_CANCEL(100rel);
-
- /* In all cases: Send 2xx PRACK */
- if(!(ret = send_RESPONSE(self, request, 200, "OK", tsk_false))){
- ++self->rseq;
- }
-
- /*
- 1. Alice sends an initial INVITE without offer
- 2. Bob's answer is sent in the first reliable provisional response, in this case it's a 1xx INVITE response
- 3. Alice's answer is sent in the PRACK response
- */
- if(!self->msession_mgr->sdp.ro){
- if(TSIP_MESSAGE_HAS_CONTENT(request)){
- if((ret = tsip_dialog_invite_process_ro(self, request))){
- /* Send Error and break the FSM */
- ret = send_ERROR(self, self->last_iInvite, 488, "Not Acceptable", "SIP; cause=488; text=\"Bad content\"");
- return -4;
- }
- }
- else{
- /* 488 INVITE */
- ret = send_ERROR(self, self->last_iInvite, 488, "Not Acceptable", "SIP; cause=488; text=\"Offer expected in the PRACK\"");
- return -3;
- }
- }
-
- return ret;
-}
-
-/* InProgress ->(iPRACK without QoS) -> Ringing */
-int s0000_InProgress_2_Ringing_X_iPRACK(va_list *app)
-{
- int ret;
-
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- /* Cancel 100rel timer */
- TSIP_DIALOG_TIMER_CANCEL(100rel);
-
- /* In all cases: Send 2xx PRACK */
- if(!(ret = send_RESPONSE(self, request, 200, "OK", tsk_false))){
- ++self->rseq;
- }
-
- /*
- 1. Alice sends an initial INVITE without offer
- 2. Bob's answer is sent in the first reliable provisional response, in this case it's a 1xx INVITE response
- 3. Alice's answer is sent in the PRACK response
- */
- if(self->msession_mgr && !self->msession_mgr->sdp.ro){
- if(TSIP_MESSAGE_HAS_CONTENT(request)){
- if((ret = tsip_dialog_invite_process_ro(self, request))){
- /* Send Error and break the FSM */
- ret = send_ERROR(self, self->last_iInvite, 488, "Not Acceptable", "SIP; cause=488; text=\"Bad content\"");
- return -4;
- }
- }
- else{
- /* 488 INVITE */
- ret = send_ERROR(self, self->last_iInvite, 488, "Not Acceptable", "SIP; cause=488; text=\"Offer expected in the PRACK\"");
- return -3;
- }
- }
-
- /* Send Ringing */
- ret = send_RESPONSE(self, self->last_iInvite, 180, "Ringing", tsk_false);
-
- /* Alert the user (session) */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_i_newcall,
- tsip_event_code_dialog_request_incoming, "Incoming Call", request);
-
- return ret;
-}
-
-/* InProgress ->(iUPDATE but cannot resume) -> InProgress */
-int s0000_InProgress_2_InProgress_X_iUPDATE(va_list *app)
-{
- int ret;
-
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- if((ret = tsip_dialog_invite_process_ro(self, request))){
- /* Send Error and break the FSM */
- ret = send_ERROR(self, request, 488, "Not Acceptable", "SIP; cause=488; text=\"Bad content\"");
- return -4;
- }
- else{
- ret = send_RESPONSE(self, request, 200, "OK", tsk_false);
- }
-
- return ret;
-}
-
-/* InProgress ->(iUPDATE can resume) -> Ringing */
-int s0000_InProgress_2_Ringing_X_iUPDATE(va_list *app)
-{
- int ret;
-
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- if((ret = tsip_dialog_invite_process_ro(self, request))){
- /* Send Error and break the FSM */
- ret = send_ERROR(self, request, 488, "Not Acceptable", "SIP; cause=488; text=\"Bad content\"");
- return -4;
- }
-
- /* Send 200 UPDATE */
- ret = send_RESPONSE(self, request, 200, "OK", tsk_false);
-
- /* Send Ringing */
- ret = send_RESPONSE(self, self->last_iInvite, 180, "Ringing", tsk_false);
-
- /* alert the user */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_i_newcall,
- tsip_event_code_dialog_request_incoming, "Incoming Call", request);
-
- return ret;
-}
-
-/* InProgress ->(iCANCEL) -> Terminated */
-int s0000_Inprogress_2_Terminated_X_iCANCEL(va_list *app)
-{
- tsip_response_t* response;
- int ret = -1;
-
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- /* Send 2xx for the CANCEL (Direct to Transport layer beacause CANCEL is a special case) */
- if((response = tsip_dialog_response_new(TSIP_DIALOG(self), 200, "OK", request))){
- ret = tsip_transport_layer_send(TSIP_DIALOG_GET_STACK(self)->layer_transport, tsk_null, response);
- TSK_OBJECT_SAFE_FREE(response);
- }
-
- /* Send Request Cancelled */
- ret = send_ERROR(self, self->last_iInvite, 487, "Request Cancelled", "SIP; cause=487; text=\"Request Cancelled\"");
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), "Call Cancelled");
-
- /* alert the user */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_i_request,
- tsip_event_code_dialog_request_incoming, "Incoming Request.", request);
-
- return ret;
-}
-
-/* Ringing -> (iPRACK) -> Ringing */
-int s0000_Ringing_2_Ringing_X_iPRACK(va_list *app)
-{
- int ret;
-
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- if(!self->last_iInvite){
- /* silently ignore */
- return 0;
- }
-
- /* Cancel 100rel timer */
- TSIP_DIALOG_TIMER_CANCEL(100rel);
-
- /* Send 2xx PRACK */
- ret = send_RESPONSE(self, request, 200, "OK", tsk_false);
-
- /* alert the user */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_i_request,
- tsip_event_code_dialog_request_incoming, "Incoming Request.", request);
-
- return ret;
-}
-
-/* Ringing -> (oAccept) -> Connected */
-int s0000_Ringing_2_Connected_X_Accept(va_list *app)
-{
- int ret;
-
- tsip_dialog_invite_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_invite_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* Update current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* Determine whether the remote party support UPDATE */
- self->support_update = tsip_message_allowed(self->last_iInvite, "UPDATE");
-
- /* Appy media params received from the user */
- if(!TSK_LIST_IS_EMPTY(action->media.params)){
- tmedia_session_mgr_set_3(self->msession_mgr, action->media.params);
- }
- /* start session manager */
- if(self->msession_mgr && !self->msession_mgr->started && (self->msession_mgr->sdp.lo && self->msession_mgr->sdp.ro)){
- /* Set MSRP Callback */
- if((self->msession_mgr->type & tmedia_msrp) == tmedia_msrp){
- tmedia_session_mgr_set_msrp_cb(self->msession_mgr, TSIP_DIALOG_GET_SS(self)->userdata, TSIP_DIALOG_GET_SS(self)->media.msrp.callback);
- }
- ret = tmedia_session_mgr_start(self->msession_mgr);
- }
-
- /* Cancel 100rel timer */
- TSIP_DIALOG_TIMER_CANCEL(100rel);
-
- /* send 2xx OK */
- ret = send_RESPONSE(self, self->last_iInvite, 200, "OK", tsk_true);
-
- /* Session Timers */
- if(self->stimers.timer.timeout){
- if(tsip_dialog_invite_stimers_isRefresher(self)){
- /* RFC 4028 - 9. UAS Behavior
- It is RECOMMENDED that this refresh be sent oncehalf the session interval has elapsed.
- Additional procedures for this refresh are described in Section 10.
- */
- tsip_dialog_invite_stimers_schedule(self, (self->stimers.timer.timeout*1000)/2);
- }
- else{
- tsip_dialog_invite_stimers_schedule(self, (self->stimers.timer.timeout*1000));
- }
- }
-
- /* alert the user (dialog) */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connected, "Dialog connected");
-
- return ret;
-}
-
-/* Ringing -> (oReject) -> Terminated */
-int s0000_Ringing_2_Terminated_X_Reject(va_list *app)
-{
- int ret;
- short code;
- const char* phrase;
- char* reason = tsk_null;
-
- tsip_dialog_invite_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_invite_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* Update current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* Cancel 100rel timer */
- TSIP_DIALOG_TIMER_CANCEL(100rel);
-
- /* Send Reject */
- code = action->line_resp.code>=300 ? action->line_resp.code : 603;
- phrase = action->line_resp.phrase ? action->line_resp.phrase : "Decline";
- tsk_sprintf(&reason, "SIP; cause=%hi; text=\"%s\"", code, phrase);
- ret = send_ERROR(self, self->last_iInvite, code, phrase, reason);
- TSK_FREE(reason);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), "Call Terminated");
-
- return ret;
-}
-
-/* Ringing ->(iCANCEL) -> Terminated */
-int s0000_Ringing_2_Terminated_X_iCANCEL(va_list *app)
-{
- int ret;
- tsip_response_t* response;
-
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- if(!self->last_iInvite){
- /* silently ignore */
- return 0;
- }
-
- /* Send 2xx for the CANCEL (Direct to Transport layer beacause CANCEL is a special case) */
- if((response = tsip_dialog_response_new(TSIP_DIALOG(self), 200, "OK", request))){
- ret = tsip_transport_layer_send(TSIP_DIALOG_GET_STACK(self)->layer_transport, tsk_null, response);
- TSK_OBJECT_SAFE_FREE(response);
- }
-
- /* Send Request Cancelled */
- ret = send_ERROR(self, self->last_iInvite, 487, "Request Cancelled", "SIP; cause=487; text=\"Request Cancelled\"");
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), "Call Cancelled");
-
- /* alert the user */
- TSIP_DIALOG_INVITE_SIGNAL(self, tsip_i_request,
- tsip_event_code_dialog_request_incoming, "Incoming Request.", request);
-
- return ret;
-}
-
-/* Any ->(timer 100rel) -> Any */
-int s0000_Any_2_Any_X_timer100rel(va_list *app)
-{
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
-
- int ret;
-
- if(!self->last_o1xxrel){
- /* silently ignore */
- return 0;
- }
-
- /* resync timer */
- if((self->timer100rel.timeout *= 2) >= (64 * tsip_timers_getA())){
- TSK_DEBUG_ERROR("Sending reliable 1xx failed");
- return -2;
- }
-
- /* resend reliable 1xx */
- if((ret = tsip_dialog_response_send(TSIP_DIALOG(self), self->last_o1xxrel))){
- return ret;
- }
- else{
- /* schedule timer */
- TSIP_DIALOG_INVITE_TIMER_SCHEDULE(100rel);
- }
-
- return ret;
-}
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-int send_UNSUPPORTED(tsip_dialog_invite_t* self, const tsip_request_t* request, const char* option)
-{
- tsip_response_t *response;
-
- if(!self || !option){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if((response = tsip_dialog_response_new(TSIP_DIALOG(self), 420, "Bad Extension", request))){
- // Add UnSupported header
- tsip_message_add_headers(response,
- TSIP_HEADER_DUMMY_VA_ARGS("Unsupported", option),
- TSIP_HEADER_DUMMY_VA_ARGS("Reason", "SIP; cause=420; text=\"Bad Extension\""),
- tsk_null
- );
-
- tsip_dialog_response_send(TSIP_DIALOG(self), response);
- TSK_OBJECT_SAFE_FREE(response);
- }
- return 0;
-}
-
-
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.timers.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.timers.c
deleted file mode 100644
index 818c168..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_invite.timers.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_invite.timers.c
- * @brief SIP dialog INVITE as per RFC 3261.
- * The SOA machine is designed as per RFC 3264 and draft-ietf-sipping-sip-offeranswer-12.
- * Session Timers as per RFC 4028.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_invite.h"
-
-#include "tinysip/headers/tsip_header_Session_Expires.h"
-#include "tinysip/headers/tsip_header_Min_SE.h"
-
-#include "tinysip/dialogs/tsip_dialog_invite.common.h"
-
-#include "tsk_debug.h"
-
-/* ======================== internal functions ======================== */
-tsk_bool_t tsip_dialog_invite_stimers_isRefresher(tsip_dialog_invite_t* self);
-
-/* ======================== external functions ======================== */
-extern int tsip_dialog_invite_timer_callback(const tsip_dialog_invite_t* self, tsk_timer_id_t timer_id);
-extern int send_RESPONSE(tsip_dialog_invite_t *self, const tsip_request_t* request, short code, const char* phrase);
-extern int send_BYE(tsip_dialog_invite_t *self);
-extern int send_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE, tsk_bool_t force_sdp);
-
-/* ======================== transitions ======================== */
-static int x0200_Connected_2_Connected_X_timerRefresh(va_list *app);
-static int x0201_Connected_2_Trying_X_timerRefresh(va_list *app);
-static int x0250_Any_2_Any_X_i422(va_list *app);
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_is_refresher(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return tsip_dialog_invite_stimers_isRefresher(self);
-}
-static tsk_bool_t _fsm_cond_is_not_refresher(tsip_dialog_invite_t* self, tsip_message_t* message)
-{
- return !_fsm_cond_is_refresher(self, message);
-}
-
-
-/* Init FSM */
-int tsip_dialog_invite_stimers_init(tsip_dialog_invite_t *self)
-{
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- // Connected -> (timerRefresh && isRefresher) -> Connected
- TSK_FSM_ADD(_fsm_state_Connected, _fsm_action_timerRefresh, _fsm_cond_is_refresher, _fsm_state_Connected, x0200_Connected_2_Connected_X_timerRefresh, "x0200_Connected_2_Connected_X_timerRefresh"),
- // Connected -> (timerRefresh && !isRefresher) -> Trying (because we will send BYE)
- TSK_FSM_ADD(_fsm_state_Connected, _fsm_action_timerRefresh, _fsm_cond_is_not_refresher, _fsm_state_Trying, x0201_Connected_2_Trying_X_timerRefresh, "x0201_Connected_2_Trying_X_timerRefresh"),
- // Any -> (i422) -> Any
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_i422, tsk_fsm_state_any, x0250_Any_2_Any_X_i422, "x0250_Any_2_Any_X_i422"),
-
- TSK_FSM_ADD_NULL());
-
- return 0;
-}
-
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-int x0200_Connected_2_Connected_X_timerRefresh(va_list *app)
-{
- /* We are the refresher and the session timedout
- ==> Refresh the session
- */
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- int ret;
-
- /* RFC 4028 - 7.4. Generating Subsequent Session Refresh Requests
-
- A re-INVITE generated to refresh the session is a normal re-INVITE,
- and an UPDATE generated to refresh a session is a normal UPDATE. If
- a UAC knows that its peer supports the UPDATE method, it is
- RECOMMENDED that UPDATE be used instead of a re-INVITE. A UA can
- make this determination if it has seen an Allow header field from its
- peer with the value 'UPDATE', or through a mid-dialog OPTIONS
- request. It is RECOMMENDED that the UPDATE request not contain an
- offer [4], but a re-INVITE SHOULD contain one, even if the details of
- the session have not changed
- */
- /* 2xx will be handled by tsip_dialog_invite_stimers_handle() */
- ret = send_INVITEorUPDATE(self, !self->support_update, tsk_false);
-
- return ret;
-}
-
-int x0201_Connected_2_Trying_X_timerRefresh(va_list *app)
-{
- /* We are not the refresher and the session timedout
- ==> send BYE
- */
- tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
- int ret;
-
- /* send BYE */
- ret = send_BYE(self);
-
- /* alert the user that the session timedout */
-
- return ret;
-}
-
-// Any -> (i422) -> Any
-int x0250_Any_2_Any_X_i422(va_list *app)
-{
- tsip_dialog_invite_t* self = va_arg(*app, tsip_dialog_invite_t *);
- const tsip_response_t* r422 = va_arg(*app, const tsip_response_t *);
-
- const tsip_header_Min_SE_t* Min_SE;
-
- /* RFC 4825 - 3. Overview of Operation
- If the Session-Expires interval is too low for a proxy (i.e., lower
- than the value of Min-SE that the proxy would wish to assert), the
- proxy rejects the request with a 422 response. That response
- contains a Min-SE header field identifying the minimum session
- interval it is willing to support. The UAC will try again, this time
- including the Min-SE header field in the request. The header field
- contains the largest Min-SE header field it observed in all 422
- responses previously received. This way, the minimum timer meets the
- constraints of all proxies along the path.
-
- RFC 4825 - 6. 422 Response Code Definition
- The 422 response MUST contain a Min-SE header field with the minimum timer for that server.
- */
-
- if((Min_SE = (const tsip_header_Min_SE_t* )tsip_message_get_header(r422, tsip_htype_Min_SE))){
- self->stimers.minse = Min_SE->delta_seconds;
- self->stimers.timer.timeout = Min_SE->delta_seconds;
- }
- else{
- TSK_DEBUG_ERROR("Invalid response (422 need Min-SE header)");
- return 0; /* Do not end the dialog */
- }
-
- /* send again the INVITE */
- return send_INVITE(self, tsk_false);
-}
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-
-
-
-
-/* Indicates whether we are the refresher or not */
-tsk_bool_t tsip_dialog_invite_stimers_isRefresher(tsip_dialog_invite_t* self)
-{
- if(!self){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_false;
- }
- return (self->is_client && tsk_striequals(self->stimers.refresher, "uac")) ||
- (!self->is_client && tsk_striequals(self->stimers.refresher, "uas"));
-}
-
-/* cancel the timer */
-int tsip_dialog_invite_stimers_cancel(tsip_dialog_invite_t* self)
-{
- return tsk_timer_mgr_global_cancel(self->stimers.timer.id);
-}
-
-/* schedule the timer */
-int tsip_dialog_invite_stimers_schedule(tsip_dialog_invite_t* self, uint64_t timeout)
-{
- /* Used in SIP requests ==> do not change the value
- self->stimers.timer.timeout = timeout;
- */
- self->stimers.timer.id = tsk_timer_mgr_global_schedule(timeout, TSK_TIMER_CALLBACK_F(tsip_dialog_invite_timer_callback), self);
-
- return 0;
-}
-
-/* handle requests/responses */
-int tsip_dialog_invite_stimers_handle(tsip_dialog_invite_t* self, const tsip_message_t* message)
-{
- /* It's up to the caller to check that (self->stimers.timer.timeout is >0)
- and message is INVITE or UPDATE or 2xxINVITE or 2xxUPDATE
- */
-
- int ret = 0;
- const tsip_header_Session_Expires_t* hdr_SessionExpires;
-
- if(!self || !message){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if(!self->stimers.timer.timeout){
- /* guard for stupide callers */
- return 0;
- }
- /* reUPDATE or reINVITE */
- if(TSIP_MESSAGE_IS_REQUEST(message) && (TSIP_REQUEST_IS_UPDATE(message) || TSIP_REQUEST_IS_INVITE(message))){
- if((hdr_SessionExpires = (const tsip_header_Session_Expires_t*)tsip_message_get_header(message, tsip_htype_Session_Expires))){
- if(hdr_SessionExpires->delta_seconds < TSIP_SESSION_EXPIRES_MIN_VALUE){
- self->stimers.minse = TSIP_SESSION_EXPIRES_MIN_VALUE;
- ret = send_RESPONSE(self, message, 422, "Session Interval Too Small");
- }
- else{
- self->stimers.timer.timeout = hdr_SessionExpires->delta_seconds;
- }
- }
- }
- /* 2xx */
- else if(TSIP_MESSAGE_IS_RESPONSE(message) && (TSIP_RESPONSE_IS_TO_INVITE(message) || TSIP_RESPONSE_IS_TO_UPDATE(message))){
- if(!TSIP_RESPONSE_IS_2XX(message)){
- /* guard for stupide callers */
- return 0;
- }
- /* Process the response only if it includes "Require: timer"
-
- RFC 4028 - 7.2. Processing a 2xx Response
- When a 2xx response to a session refresh request arrives, it may or
- may not contain a Require header field with the value 'timer'. If it
- does, the UAC MUST look for the Session-Expires header field to
- process the response.
-
- If there was a Require header field in the response with the value
- 'timer', the Session-Expires header field will always be present.
- UACs MUST be prepared to receive a Session-Expires header field in a
- response, even if none were present in the request. The 'refresher'
- parameter will be present in the Session-Expires header field,
- indicating who will perform the refreshes. The UAC MUST set the
- identity of the refresher to the value of this parameter. If the
- parameter contains the value 'uac', the UAC will perform them.
- */
- if(tsip_message_required(message, "timer")){
- if((hdr_SessionExpires = (const tsip_header_Session_Expires_t*)tsip_message_get_header(message, tsip_htype_Session_Expires))){
- if(hdr_SessionExpires->delta_seconds < TSIP_SESSION_EXPIRES_MIN_VALUE){
- self->stimers.minse = TSIP_SESSION_EXPIRES_MIN_VALUE;
- ret = send_RESPONSE(self, message, 422, "Interval Too short");
- }
- else{
- self->stimers.timer.timeout = hdr_SessionExpires->delta_seconds;
- if(tsk_strnullORempty(self->stimers.refresher)){
- tsk_strupdate(&self->stimers.refresher, hdr_SessionExpires->refresher_uas ? "uas" : "uac");
- }
- self->supported.timer = (self->stimers.timer.timeout != 0);
- }
- }
- else{
- self->stimers.timer.timeout = 0; /* turned-off */
- ret = send_RESPONSE(self, message, 481, "Session-Expires header is missing");
- return 0;
- }
- }
- else{
- /*
- RFC 4028 - 7.2. Processing a 2xx Response
- If the 2xx response did not contain a Session-Expires header field,
- there is no session expiration. In this case, no refreshes need to
- be sent. A 2xx without a Session-Expires can come for both initial
- and subsequent session refresh requests. This means that the session
- timer can be 'turned-off' in mid dialog by receiving a response
- without a Session-Expires header field.
- */
- self->stimers.timer.timeout = 0; /* turned-off */
- self->supported.timer = tsk_false;
- }
- }
-
- /* Cancel timeout */
- tsip_dialog_invite_stimers_cancel(self);
-
- /* schedule timer */
- if(self->stimers.timer.timeout){
- if(tsip_dialog_invite_stimers_isRefresher(self)){
- /* RFC 4028 - 9. UAS Behavior
- It is RECOMMENDED that this refresh be sent oncehalf the session interval has elapsed.
- Additional procedures for this refresh are described in Section 10.
- */
- tsip_dialog_invite_stimers_schedule(self, (self->stimers.timer.timeout*1000)/2);
- }
- else{
- tsip_dialog_invite_stimers_schedule(self, (self->stimers.timer.timeout*1000));
- }
- }
-
- return ret;
-}
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_layer.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_layer.c
deleted file mode 100644
index 959f3dd..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_layer.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_layer.c
- * @brief SIP dialog layer.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_layer.h"
-
-#include "tinysip/dialogs/tsip_dialog_invite.h"
-#include "tinysip/dialogs/tsip_dialog_message.h"
-#include "tinysip/dialogs/tsip_dialog_options.h"
-#include "tinysip/dialogs/tsip_dialog_publish.h"
-#include "tinysip/dialogs/tsip_dialog_register.h"
-#include "tinysip/dialogs/tsip_dialog_subscribe.h"
-
-#include "tinysip/transactions/tsip_transac_layer.h"
-#include "tinysip/transports/tsip_transport_layer.h"
-
-#include "tsk_debug.h"
-
-extern tsip_ssession_handle_t *tsip_ssession_create_2(const tsip_stack_t* stack, const struct tsip_message_s* message);
-
-/*== Predicate function to find dialog by type */
-static int pred_find_dialog_by_type(const tsk_list_item_t *item, const void *type)
-{
- if(item && item->data){
- tsip_dialog_t *dialog = item->data;
- return (dialog->type - *((tsip_dialog_type_t*)type));
- }
- return -1;
-}
-
-/*== Predicate function to find dialog by not type */
-static int pred_find_dialog_by_not_type(const tsk_list_item_t *item, const void *type)
-{
- if(item && item->data){
- tsip_dialog_t *dialog = item->data;
- if(dialog->type != *((tsip_dialog_type_t*)type)){
- return 0;
- }
- }
- return -1;
-}
-
-tsip_dialog_layer_t* tsip_dialog_layer_create(tsip_stack_t* stack)
-{
- return tsk_object_new(tsip_dialog_layer_def_t, stack);
-}
-
-// it's up to the caller to release the returned object
-tsip_dialog_t* tsip_dialog_layer_find_by_ss(tsip_dialog_layer_t *self, const tsip_ssession_handle_t *ss)
-{
- tsip_dialog_t *ret = 0;
- tsip_dialog_t *dialog;
- tsk_list_item_t *item;
-
- tsk_safeobj_lock(self);
-
- tsk_list_foreach(item, self->dialogs){
- dialog = item->data;
- if( tsip_ssession_get_id(dialog->ss) == tsip_ssession_get_id(ss) ){
- ret = dialog;
- break;
- }
- }
-
- tsk_safeobj_unlock(self);
-
- return tsk_object_ref(ret);
-}
-
-// it's up to the caller to release the returned object
-tsip_dialog_t* tsip_dialog_layer_find(const tsip_dialog_layer_t *self, const char* callid, const char* to_tag, const char* from_tag, tsip_request_type_t type, tsk_bool_t *cid_matched)
-{
- tsip_dialog_t *ret = tsk_null;
- tsip_dialog_t *dialog;
- tsk_list_item_t *item;
-
- *cid_matched = tsk_false;
-
- tsk_safeobj_lock(self);
-
- tsk_list_foreach(item, self->dialogs){
- dialog = item->data;
- if(tsk_strequals(dialog->callid, callid)){
- tsk_bool_t is_cancel = (type == tsip_CANCEL); // Incoming CANCEL
- tsk_bool_t is_register = (type == tsip_REGISTER); // Incoming REGISTER
- *cid_matched = tsk_true;
- /* CANCEL Request will have the same local tag than the INVITE request -> do not compare tags */
- if((is_cancel || tsk_strequals(dialog->tag_local, from_tag)) && tsk_strequals(dialog->tag_remote, to_tag)){
- ret = tsk_object_ref(dialog);
- break;
- }
- /* REGISTER is dialogless which means that each reREGISTER or unREGISTER will have empty to tag */
- if(is_register /* Do not check tags */){
- ret = tsk_object_ref(dialog);
- break;
- }
- }
- }
-
- tsk_safeobj_unlock(self);
-
- return ret;
-}
-
-/** Hangup all dialogs staring by REGISTER */
-int tsip_dialog_layer_shutdownAll(tsip_dialog_layer_t *self)
-{
- if(self){
- tsk_bool_t wait = tsk_false;
- tsk_list_item_t *item;
- tsip_dialog_t *dialog;
- tsip_dialog_type_t regtype = tsip_dialog_REGISTER;
-
- if(!self->shutdown.inprogress){
- self->shutdown.inprogress = tsk_true;
- self->shutdown.condwait = tsk_condwait_create();
- }
-
- tsk_safeobj_lock(self);
- if(tsk_list_count(self->dialogs, pred_find_dialog_by_not_type, &regtype)){
- /* There are non-register dialogs ==> phase-1 */
- goto phase1;
- }
- else if(tsk_list_count(self->dialogs, pred_find_dialog_by_type, &regtype)){
- /* There are one or more register dialogs ==> phase-2 */
- goto phase2;
- }
- else{
- tsk_safeobj_unlock(self);
- goto done;
- }
-
-phase1:
- /* Phase 1 - shutdown all except register and silent_hangup */
- TSK_DEBUG_INFO("== Shutting down - Phase-1 started ==");
-phase1_loop:
- tsk_list_foreach(item, self->dialogs){
- dialog = item->data;
- if(dialog->type != tsip_dialog_REGISTER && !dialog->ss->silent_hangup){
- item = tsk_object_ref(item);
- if(!tsip_dialog_shutdown(dialog, tsk_null)){
- wait = tsk_true;
- }
-
- // if "tsip_dialog_shutdown()" remove the dialog, then
- // "self->dialogs" will be unsafe
- if(!(item = tsk_object_unref(item))){
- goto phase1_loop;
- }
- }
- }
- tsk_safeobj_unlock(self);
-
- /* wait until phase-1 is completed */
- if(wait){
- tsk_condwait_timedwait(self->shutdown.condwait, TSIP_DIALOG_SHUTDOWN_TIMEOUT);
- }
-
- /* lock and goto phase2 */
- tsk_safeobj_lock(self);
- wait = tsk_false;
- goto phase2;
-
-phase2:
- /* Phase 2 - unregister */
- TSK_DEBUG_INFO("== Shutting down - Phase-2 started ==");
- self->shutdown.phase2 = tsk_true;
-phase2_loop:
- tsk_list_foreach(item, self->dialogs){
- dialog = item->data;
- if(dialog->type == tsip_dialog_REGISTER){
- item = tsk_object_ref(item);
- if(!tsip_dialog_shutdown(dialog, tsk_null)){
- wait = tsk_true;
- }
- // if "tsip_dialog_shutdown()" remove the dialog, then
- // "self->dialogs" will be unsafe
- if(!(item = tsk_object_unref(item))){
- goto phase2_loop;
- }
- }
- }
- tsk_safeobj_unlock(self);
-
- /* wait until phase-2 is completed */
- if(wait){
- tsk_condwait_timedwait(self->shutdown.condwait, TSIP_DIALOG_SHUTDOWN_TIMEOUT);
- }
-
-
- /* Phase 3 - silenthangup (dialogs will be terminated immediately) */
- TSK_DEBUG_INFO("== Shutting down - Phase-3 ==");
-phase3_loop:
- tsk_list_foreach(item, self->dialogs){
- dialog = item->data;
- if(dialog->ss->silent_hangup){
- item = tsk_object_ref(item);
- tsip_dialog_shutdown(dialog, tsk_null);
-
- // if "tsip_dialog_shutdown()" remove the dialog, then
- // "self->dialogs" will be unsafe
- if(!(item = tsk_object_unref(item))){
- goto phase3_loop;
- }
- }
- }
-
-done:
- return 0;
- }
- return -1;
-}
-
-/* the caller of this function must unref() the returned object */
-tsip_dialog_t* tsip_dialog_layer_new(tsip_dialog_layer_t *self, tsip_dialog_type_t type, const tsip_ssession_t *ss)
-{
- tsip_dialog_t* ret = tsk_null;
- tsip_dialog_t* dialog;
- if(!self){
- goto bail;
- }
-
- switch(type){
- case tsip_dialog_INVITE:
- {
- if((dialog = (tsip_dialog_t*)tsip_dialog_invite_create(ss, tsk_null))){
- ret = tsk_object_ref(dialog);
- tsk_list_push_back_data(self->dialogs, (void**)&dialog);
- }
- break;
- }
- case tsip_dialog_MESSAGE:
- {
- if((dialog = (tsip_dialog_t*)tsip_dialog_message_create(ss))){
- ret = tsk_object_ref(dialog);
- tsk_list_push_back_data(self->dialogs, (void**)&dialog);
- }
- break;
- }
- case tsip_dialog_OPTIONS:
- {
- if((dialog = (tsip_dialog_t*)tsip_dialog_options_create(ss))){
- ret = tsk_object_ref(dialog);
- tsk_list_push_back_data(self->dialogs, (void**)&dialog);
- }
- break;
- }
- case tsip_dialog_PUBLISH:
- {
- if((dialog = (tsip_dialog_t*)tsip_dialog_publish_create(ss))){
- ret = tsk_object_ref(dialog);
- tsk_list_push_back_data(self->dialogs, (void**)&dialog);
- }
- break;
- }
- case tsip_dialog_REGISTER:
- {
- if((dialog = (tsip_dialog_t*)tsip_dialog_register_create(ss, tsk_null))){
- ret = tsk_object_ref(dialog);
- tsk_list_push_back_data(self->dialogs, (void**)&dialog);
- }
- break;
- }
- case tsip_dialog_SUBSCRIBE:
- {
- if((dialog = (tsip_dialog_t*)tsip_dialog_subscribe_create(ss))){
- ret = tsk_object_ref(dialog);
- tsk_list_push_back_data(self->dialogs, (void**)&dialog);
- }
- break;
- }
-
- default:
- {
- TSK_DEBUG_ERROR("Dialog type not supported.");
- break;
- }
- }
-
-bail:
- return ret;
-}
-
-int tsip_dialog_layer_remove(tsip_dialog_layer_t *self, const tsip_dialog_t *dialog)
-{
- if(dialog && self){
- tsip_dialog_type_t regtype = tsip_dialog_REGISTER;
- tsk_safeobj_lock(self);
-
- /* remove the dialog */
- tsk_list_remove_item_by_data(self->dialogs, dialog);
-
- /* whether shutting down? */
- if(self->shutdown.inprogress){
- if(self->shutdown.phase2){ /* Phase 2 (all non-REGISTER and silent dialogs have been removed) */
- if(tsk_list_count(self->dialogs, pred_find_dialog_by_type, &regtype) == 0){
- /* alert only if there is not REGISTER dialog (ignore silents) */
- TSK_DEBUG_INFO("== Shutting down - Phase-2 completed ==");
- tsk_condwait_broadcast(self->shutdown.condwait);
- }
- }
- else{ /* Phase 1 */
- if(tsk_list_count(self->dialogs, pred_find_dialog_by_not_type, &regtype) == 0){
- /* alert only if all dialogs except REGISTER have been removed */
- TSK_DEBUG_INFO("== Shutting down - Phase-1 completed ==");
- tsk_condwait_broadcast(self->shutdown.condwait);
- }
- }
- }
-
- tsk_safeobj_unlock(self);
-
- return 0;
- }
-
- return -1;
-}
-
-int tsip_dialog_layer_handle_incoming_msg(const tsip_dialog_layer_t *self, const tsip_message_t* message)
-{
- int ret = -1;
- tsk_bool_t cid_matched;
- tsip_dialog_t* dialog;
- tsip_transac_t* transac = tsk_null;
- const tsip_transac_layer_t *layer_transac = self->stack->layer_transac;
-
- if(!layer_transac){
- goto bail;
- }
-
- //tsk_safeobj_lock(self);
- dialog = tsip_dialog_layer_find(self, message->Call_ID->value,
- TSIP_MESSAGE_IS_RESPONSE(message) ? message->To->tag : message->From->tag,
- TSIP_MESSAGE_IS_RESPONSE(message) ? message->From->tag : message->To->tag,
- TSIP_MESSAGE_IS_REQUEST(message) ? TSIP_MESSAGE_AS_REQUEST(message)->line.request.request_type : tsip_NONE,
- &cid_matched);
- //tsk_safeobj_unlock(self);
-
- if(dialog){
- if(TSIP_REQUEST_IS_CANCEL(message) || TSIP_REQUEST_IS_ACK(message)){
- ret = dialog->callback(dialog, tsip_dialog_i_msg, message);
- tsk_object_unref(dialog);
- goto bail;
- }
- else{
- transac = tsip_transac_layer_new(layer_transac, tsk_false, message, TSIP_DIALOG(dialog));
- tsk_object_unref(dialog);
- }
- }
- else{
- if(TSIP_MESSAGE_IS_REQUEST(message)){
- tsip_ssession_t* ss = tsk_null;
- tsip_dialog_t* newdialog = tsk_null;
-
- switch(message->line.request.request_type){
- case tsip_MESSAGE:
- { /* Server incoming MESSAGE */
- if((ss = tsip_ssession_create_2(self->stack, message))){
- newdialog = (tsip_dialog_t*)tsip_dialog_message_create(ss);
- }
- break;
- }
-
- case tsip_REGISTER:
- { /* incoming REGISTER */
- if((ss = tsip_ssession_create_2(self->stack, message))){
- newdialog = (tsip_dialog_t*)tsip_dialog_register_create(ss, message->Call_ID ? message->Call_ID->value : tsk_null);
- }
- break;
- }
-
- case tsip_INVITE:
- { /* incoming INVITE */
- if((ss = tsip_ssession_create_2(self->stack, message))){
- newdialog = (tsip_dialog_t*)tsip_dialog_invite_create(ss, message->Call_ID ? message->Call_ID->value : tsk_null);
- }
- break;
- }
-
- default:
- {
- break;
- }
- }//switch
-
- if(newdialog){
- transac = tsip_transac_layer_new(layer_transac, tsk_false, message, newdialog);
- tsk_list_push_back_data(self->dialogs, (void**)&newdialog); /* add new dialog to the layer */
- }
-
- /* The dialog will become the owner of the SIP session
- * => when destoyed => SIP session will be destroyed, unless the user-end takes ownership() */
- TSK_OBJECT_SAFE_FREE(ss);
- }
- }
-
- if(transac){
- ret = tsip_transac_start(transac, message);
- tsk_object_unref(transac);
- }
- else if(TSIP_MESSAGE_IS_REQUEST(message)){ /* No transaction match for the SIP request */
- const tsip_transport_layer_t *layer;
- tsip_response_t* response = tsk_null;
-
- if((layer = self->stack->layer_transport)){
- if(cid_matched){ /* We are receiving our own message. */
- response = tsip_response_new(482, "Loop Detected (Check your iFCs)", message);
- if(response && !response->To->tag){/* Early dialog? */
- response->To->tag = tsk_strdup("doubango");
- }
- }
- else{
- response = tsip_response_new(481, "Dialog/Transaction Does Not Exist", message);
- }
- if(response){
- ret = tsip_transport_layer_send(layer, response->firstVia ? response->firstVia->branch : "no-branch", response);
- TSK_OBJECT_SAFE_FREE(response);
- }
- }
- }
-
-bail:
- return ret;
-}
-
-
-
-
-
-//========================================================
-// Dialog layer object definition
-//
-static tsk_object_t* tsip_dialog_layer_ctor(tsk_object_t * self, va_list * app)
-{
- tsip_dialog_layer_t *layer = self;
- if(layer){
- layer->stack = va_arg(*app, const tsip_stack_t *);
- layer->dialogs = tsk_list_create();
-
- tsk_safeobj_init(layer);
- }
- return self;
-}
-
-static tsk_object_t* tsip_dialog_layer_dtor(tsk_object_t * self)
-{
- tsip_dialog_layer_t *layer = self;
- if(layer){
- TSK_OBJECT_SAFE_FREE(layer->dialogs);
-
- /* condwait */
- if(layer->shutdown.condwait){
- tsk_condwait_destroy(&layer->shutdown.condwait);
- }
-
- tsk_safeobj_deinit(layer);
-
- TSK_DEBUG_INFO("*** Dialog Layer destroyed ***");
- }
- return self;
-}
-
-static int tsip_dialog_layer_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
-{
- return -1;
-}
-
-static const tsk_object_def_t tsip_dialog_layer_def_s =
-{
- sizeof(tsip_dialog_layer_t),
- tsip_dialog_layer_ctor,
- tsip_dialog_layer_dtor,
- tsip_dialog_layer_cmp,
-};
-const tsk_object_def_t *tsip_dialog_layer_def_t = &tsip_dialog_layer_def_s;
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_message.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_message.c
deleted file mode 100644
index 3d0e5b9..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_message.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_message.c
- * @brief SIP dialog message (Client side).
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_message.h"
-#include "tinysip/parsers/tsip_parser_uri.h"
-
-#include "tinysip/api/tsip_api_message.h"
-
-#include "tinysip/headers/tsip_header_Dummy.h"
-#include "tinysip/headers/tsip_header_Min_Expires.h"
-
-#include "tinysip/transactions/tsip_transac_layer.h"
-
-#include "tsk_memory.h"
-#include "tsk_debug.h"
-#include "tsk_time.h"
-
-#define DEBUG_STATE_MACHINE 1
-#define TSIP_DIALOG_MESSAGE_SIGNAL(self, type, code, phrase, message) \
- tsip_message_event_signal(type, TSIP_DIALOG(self)->ss, code, phrase, message)
-
-/* ======================== internal functions ======================== */
-int send_MESSAGE(tsip_dialog_message_t *self);
-int tsip_dialog_message_OnTerminated(tsip_dialog_message_t *self);
-
-/* ======================== transitions ======================== */
-int tsip_dialog_message_Started_2_Sending_X_sendMESSAGE(va_list *app);
-int tsip_dialog_message_Started_2_Receiving_X_recvMESSAGE(va_list *app);
-int tsip_dialog_message_Sending_2_Sending_X_1xx(va_list *app);
-int tsip_dialog_message_Sending_2_Terminated_X_2xx(va_list *app);
-int tsip_dialog_message_Sending_2_Sending_X_401_407_421_494(va_list *app);
-int tsip_dialog_message_Sending_2_Terminated_X_300_to_699(va_list *app);
-int tsip_dialog_message_Sending_2_Terminated_X_cancel(va_list *app);
-int tsip_dialog_message_Receiving_2_Terminated_X_accept(va_list *app);
-int tsip_dialog_message_Receiving_2_Terminated_X_reject(va_list *app);
-int tsip_dialog_message_Any_2_Terminated_X_transportError(va_list *app);
-int tsip_dialog_message_Any_2_Terminated_X_Error(va_list *app);
-
-/* ======================== conds ======================== */
-
-/* ======================== actions ======================== */
-typedef enum _fsm_action_e
-{
- _fsm_action_sendMESSAGE = tsip_atype_message_send,
- _fsm_action_accept = tsip_atype_accept,
- _fsm_action_reject = tsip_atype_reject,
- _fsm_action_cancel = tsip_atype_cancel,
- _fsm_action_shutdown = tsip_atype_shutdown,
-
- _fsm_action_receiveMESSAGE = 0xFF,
- _fsm_action_1xx,
- _fsm_action_2xx,
- _fsm_action_401_407_421_494,
- _fsm_action_300_to_699,
- _fsm_action_transporterror,
- _fsm_action_error,
-}
-_fsm_action_t;
-
-/* ======================== states ======================== */
-typedef enum _fsm_state_e
-{
- _fsm_state_Started,
- _fsm_state_Sending,
- _fsm_state_Receiving,
- _fsm_state_Terminated
-}
-_fsm_state_t;
-
-
-int tsip_dialog_message_event_callback(const tsip_dialog_message_t *self, tsip_dialog_event_type_t type, const tsip_message_t *msg)
-{
- int ret = -1;
-
- switch(type)
- {
- case tsip_dialog_i_msg:
- {
- if(msg)
- {
- if(TSIP_MESSAGE_IS_RESPONSE(msg))
- {
- if(TSIP_RESPONSE_IS_1XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_1xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS_2XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_2xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_CODE(msg) == 401 || TSIP_RESPONSE_CODE(msg) == 407 || TSIP_RESPONSE_CODE(msg) == 421 || TSIP_RESPONSE_CODE(msg) == 494){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_401_407_421_494, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS_3456(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_300_to_699, msg, tsk_null);
- }
- else{ /* Should never happen */
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_error, msg, tsk_null);
- }
- }
- else if (TSIP_REQUEST_IS_MESSAGE(msg)){ /* have been checked by dialog layer...but */
- // REQUEST ==> Incoming MESSAGE
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_receiveMESSAGE, msg, tsk_null);
- }
- }
- break;
- }
-
- case tsip_dialog_canceled:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_cancel, msg, tsk_null);
- break;
- }
-
- case tsip_dialog_terminated:
- case tsip_dialog_timedout:
- case tsip_dialog_error:
- case tsip_dialog_transport_error:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_transporterror, msg, tsk_null);
- break;
- }
- }
-
- return ret;
-}
-
-tsip_dialog_message_t* tsip_dialog_message_create(const tsip_ssession_handle_t* ss)
-{
- return tsk_object_new(tsip_dialog_message_def_t, ss);
-}
-
-int tsip_dialog_message_init(tsip_dialog_message_t *self)
-{
- //const tsk_param_t* param;
-
- /* Initialize the state machine. */
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Started ===
- */
- // Started -> (send) -> Sending
- TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_sendMESSAGE, _fsm_state_Sending, tsip_dialog_message_Started_2_Sending_X_sendMESSAGE, "tsip_dialog_message_Started_2_Sending_X_sendMESSAGE"),
- // Started -> (receive) -> Receiving
- TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_receiveMESSAGE, _fsm_state_Receiving, tsip_dialog_message_Started_2_Receiving_X_recvMESSAGE, "tsip_dialog_message_Started_2_Receiving_X_recvMESSAGE"),
- // Started -> (Any) -> Started
- TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_dialog_message_Started_2_Started_X_any"),
-
-
- /*=======================
- * === Sending ===
- */
- // Sending -> (1xx) -> Sending
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_1xx, _fsm_state_Sending, tsip_dialog_message_Sending_2_Sending_X_1xx, "tsip_dialog_message_Sending_2_Sending_X_1xx"),
- // Sending -> (2xx) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_2xx, _fsm_state_Terminated, tsip_dialog_message_Sending_2_Terminated_X_2xx, "tsip_dialog_message_Sending_2_Terminated_X_2xx"),
- // Sending -> (401/407/421/494) -> Sending
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_401_407_421_494, _fsm_state_Sending, tsip_dialog_message_Sending_2_Sending_X_401_407_421_494, "tsip_dialog_message_Sending_2_Sending_X_401_407_421_494"),
- // Sending -> (300_to_699) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_300_to_699, _fsm_state_Terminated, tsip_dialog_message_Sending_2_Terminated_X_300_to_699, "tsip_dialog_message_Sending_2_Terminated_X_300_to_699"),
- // Sending -> (cancel) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_cancel, _fsm_state_Terminated, tsip_dialog_message_Sending_2_Terminated_X_cancel, "tsip_dialog_message_Sending_2_Terminated_X_cancel"),
- // Sending -> (shutdown) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_shutdown, _fsm_state_Terminated, tsk_null, "tsip_dialog_message_Sending_2_Terminated_X_shutdown"),
- // Sending -> (Any) -> Sending
- TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Sending, "tsip_dialog_message_Sending_2_Sending_X_any"),
-
- /*=======================
- * === Receiving ===
- */
- // Receiving -> (accept) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Receiving, _fsm_action_accept, _fsm_state_Terminated, tsip_dialog_message_Receiving_2_Terminated_X_accept, "tsip_dialog_message_Receiving_2_Terminated_X_accept"),
- // Receiving -> (rejected) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Receiving, _fsm_action_reject, _fsm_state_Terminated, tsip_dialog_message_Receiving_2_Terminated_X_reject, "tsip_dialog_message_Receiving_2_Terminated_X_reject"),
- // Receiving -> (Any) -> Receiving
- TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Receiving, "tsip_dialog_message_Receiving_2_Receiving_X_any"),
-
- /*=======================
- * === Any ===
- */
- // Any -> (transport error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_dialog_message_Any_2_Terminated_X_transportError, "tsip_dialog_message_Any_2_Terminated_X_transportError"),
- // Any -> (transport error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_dialog_message_Any_2_Terminated_X_Error, "tsip_dialog_message_Any_2_Terminated_X_Error"),
-
- TSK_FSM_ADD_NULL());
-
- TSIP_DIALOG(self)->callback = TSIP_DIALOG_EVENT_CALLBACK_F(tsip_dialog_message_event_callback);
-
- return 0;
-}
-
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-
-/* Started -> (sendMESSAGE) -> Sending
-*/
-int tsip_dialog_message_Started_2_Sending_X_sendMESSAGE(va_list *app)
-{
- tsip_dialog_message_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_message_t *);
- va_arg(*app, tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- TSIP_DIALOG(self)->running = tsk_true;
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- return send_MESSAGE(self);
-}
-
-/* Started -> (recvMESSAGE) -> Receiving
-*/
-int tsip_dialog_message_Started_2_Receiving_X_recvMESSAGE(va_list *app)
-{
- tsip_dialog_message_t *self = va_arg(*app, tsip_dialog_message_t *);
- const tsip_request_t *request = va_arg(*app, const tsip_request_t *);
-
- /* Alert the user. */
- TSIP_DIALOG_MESSAGE_SIGNAL(self, tsip_i_message,
- tsip_event_code_dialog_request_incoming, "Incoming Request.", request);
-
- /* Update last incoming MESSAGE */
- TSK_OBJECT_SAFE_FREE(self->last_iMessage);
- self->last_iMessage = tsk_object_ref((void*)request);
-
- return 0;
-}
-
-/* Sending -> (1xx) -> Sending
-*/
-int tsip_dialog_message_Sending_2_Sending_X_1xx(va_list *app)
-{
- /*tsip_dialog_message_t *self = va_arg(*app, tsip_dialog_message_t *);*/
- /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/
-
- return 0;
-}
-
-/* Sending -> (2xx) -> Sending
-*/
-int tsip_dialog_message_Sending_2_Terminated_X_2xx(va_list *app)
-{
- tsip_dialog_message_t *self = va_arg(*app, tsip_dialog_message_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* Alert the user. */
- TSIP_DIALOG_MESSAGE_SIGNAL(self, tsip_ao_message,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- /* Reset curr action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), tsk_null);
-
- return 0;
-}
-
-/* Sending -> (401/407/421/494) -> Sending
-*/
-int tsip_dialog_message_Sending_2_Sending_X_401_407_421_494(va_list *app)
-{
- /*tsip_dialog_message_t *self = va_arg(*app, tsip_dialog_message_t *);*/
- /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/
-
- return 0;
-}
-
-/* Sending -> (300 to 699) -> Terminated
-*/
-int tsip_dialog_message_Sending_2_Terminated_X_300_to_699(va_list *app)
-{
- tsip_dialog_message_t *self = va_arg(*app, tsip_dialog_message_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), TSIP_RESPONSE_PHRASE(response));
-
- /* Alert the user. */
- TSIP_DIALOG_MESSAGE_SIGNAL(self, tsip_ao_message,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return 0;
-}
-
-/* Sending -> (cancel) -> Terminated
-*/
-int tsip_dialog_message_Sending_2_Terminated_X_cancel(va_list *app)
-{
- tsip_dialog_message_t *self = va_arg(*app, tsip_dialog_message_t *);
- /* const tsip_message_t *message = va_arg(*app, const tsip_message_t *); */
-
- /* RFC 3261 - 9.1 Client Behavior
- A CANCEL request SHOULD NOT be sent to cancel a request other than INVITE.
- */
-
- /* Cancel all transactions associated to this dialog (will also be done when the dialog is destroyed (worth nothing)) */
- tsip_transac_layer_cancel_by_dialog(TSIP_DIALOG_GET_STACK(self)->layer_transac, TSIP_DIALOG(self));
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_request_cancelled, "MESSAGE cancelled");
-
- return 0;
-}
-
-/* Receiving -> (accept) -> Terminated
-*/
-int tsip_dialog_message_Receiving_2_Terminated_X_accept(va_list *app)
-{
- tsip_dialog_message_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_message_t *);
- va_arg(*app, tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- if(!self->last_iMessage){
- TSK_DEBUG_ERROR("There is non MESSAGE to accept()");
- /* Not an error ...but do not update current action */
- }
- else{
- tsip_response_t *response;
- int ret;
-
- /* curr_action is only used for outgoing requests */
- /* tsip_dialog_set_curr_action(TSIP_DIALOG(self), action); */
-
- /* send 200 OK */
- if((response = tsip_dialog_response_new(TSIP_DIALOG(self), 200, "OK", self->last_iMessage))){
- tsip_dialog_apply_action(response, action); /* apply action params to "this" response */
- if((ret = tsip_dialog_response_send(TSIP_DIALOG(self), response))){
- TSK_DEBUG_ERROR("Failed to send SIP response.");
- TSK_OBJECT_SAFE_FREE(response);
- return ret;
- }
- TSK_OBJECT_SAFE_FREE(response);
- }
- else{
- TSK_DEBUG_ERROR("Failed to create SIP response.");
- return -1;
- }
- }
-
- return 0;
-}
-
-/* Receiving -> (reject) -> Terminated
-*/
-int tsip_dialog_message_Receiving_2_Terminated_X_reject(va_list *app)
-{
- tsip_dialog_message_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_message_t *);
- va_arg(*app, tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- if(!self->last_iMessage){
- TSK_DEBUG_ERROR("There is non MESSAGE to reject()");
- /* Not an error ...but do not update current action */
- }
- else{
- tsip_response_t *response;
- int ret;
-
- /* curr_action is only used for outgoing requests */
- /* tsip_dialog_set_curr_action(TSIP_DIALOG(self), action); */
-
- /* send 486 Rejected */
- if((response = tsip_dialog_response_new(TSIP_DIALOG(self), 486, "Rejected", self->last_iMessage))){
- tsip_dialog_apply_action(response, action); /* apply action params to "this" response */
- if((ret = tsip_dialog_response_send(TSIP_DIALOG(self), response))){
- TSK_DEBUG_ERROR("Failed to send SIP response.");
- TSK_OBJECT_SAFE_FREE(response);
- return ret;
- }
- TSK_OBJECT_SAFE_FREE(response);
- }
- else{
- TSK_DEBUG_ERROR("Failed to create SIP response.");
- return -1;
- }
- }
-
- return 0;
-}
-
-/* Any -> (transport error) -> Terminated
-*/
-int tsip_dialog_message_Any_2_Terminated_X_transportError(va_list *app)
-{
- /*tsip_dialog_message_t *self = va_arg(*app, tsip_dialog_message_t *);*/
- /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/
-
- return 0;
-}
-
-/* Any -> (error) -> Terminated
-*/
-int tsip_dialog_message_Any_2_Terminated_X_Error(va_list *app)
-{
- /*tsip_dialog_message_t *self = va_arg(*app, tsip_dialog_message_t *);*/
- /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/
-
- return 0;
-}
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-int send_MESSAGE(tsip_dialog_message_t *self)
-{
- tsip_request_t* request = tsk_null;
- int ret = -1;
-
- if(!self){
- return -1;
- }
-
- if(!(request = tsip_dialog_request_new(TSIP_DIALOG(self), "MESSAGE"))){
- return -2;
- }
-
- /* apply action params to the request */
- if(TSIP_DIALOG(self)->curr_action){
- tsip_dialog_apply_action(request, TSIP_DIALOG(self)->curr_action);
- }
-
- ret = tsip_dialog_request_send(TSIP_DIALOG(self), request);
- TSK_OBJECT_SAFE_FREE(request);
-
- return ret;
-}
-
-
-int tsip_dialog_message_OnTerminated(tsip_dialog_message_t *self)
-{
- TSK_DEBUG_INFO("=== MESSAGE Dialog terminated ===");
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminated,
- TSIP_DIALOG(self)->lasterror ? TSIP_DIALOG(self)->lasterror : "Dialog terminated");
-
- /* Remove from the dialog layer. */
- return tsip_dialog_remove(TSIP_DIALOG(self));
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-//========================================================
-// SIP dialog MESSAGE object definition
-//
-static tsk_object_t* tsip_dialog_message_ctor(tsk_object_t * self, va_list * app)
-{
- tsip_dialog_message_t *dialog = self;
- if(dialog){
- tsip_ssession_handle_t *ss = va_arg(*app, tsip_ssession_handle_t *);
-
- /* Initialize base class */
- tsip_dialog_init(TSIP_DIALOG(self), tsip_dialog_MESSAGE, tsk_null, ss, _fsm_state_Started, _fsm_state_Terminated);
-
- /* FSM */
- TSIP_DIALOG_GET_FSM(self)->debug = DEBUG_STATE_MACHINE;
- tsk_fsm_set_callback_terminated(TSIP_DIALOG_GET_FSM(self), TSK_FSM_ONTERMINATED_F(tsip_dialog_message_OnTerminated), (const void*)dialog);
-
- /* Initialize the class itself */
- tsip_dialog_message_init(self);
- }
- return self;
-}
-
-static tsk_object_t* tsip_dialog_message_dtor(tsk_object_t * self)
-{
- tsip_dialog_message_t *dialog = self;
- if(dialog){
- /* DeInitialize base class (will cancel all transactions) */
- tsip_dialog_deinit(TSIP_DIALOG(self));
-
- /* DeInitialize self */
- TSK_OBJECT_SAFE_FREE(dialog->last_iMessage);
-
- TSK_DEBUG_INFO("*** MESSAGE Dialog destroyed ***");
- }
- return self;
-}
-
-static int tsip_dialog_message_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
-{
- return tsip_dialog_cmp(obj1, obj2);
-}
-
-static const tsk_object_def_t tsip_dialog_message_def_s =
-{
- sizeof(tsip_dialog_message_t),
- tsip_dialog_message_ctor,
- tsip_dialog_message_dtor,
- tsip_dialog_message_cmp,
-};
-const tsk_object_def_t *tsip_dialog_message_def_t = &tsip_dialog_message_def_s;
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_options.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_options.c
deleted file mode 100644
index 42e635c..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_options.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_options.c
- * @brief SIP dialog OPTIONS as per RFC 3261 section 11.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_options.h"
-#include "tinysip/parsers/tsip_parser_uri.h"
-
-#include "tinysip/api/tsip_api_options.h"
-
-#include "tinysip/headers/tsip_header_Dummy.h"
-#include "tinysip/headers/tsip_header_Min_Expires.h"
-
-#include "tinysip/transactions/tsip_transac_layer.h"
-
-#include "tsk_memory.h"
-#include "tsk_debug.h"
-#include "tsk_time.h"
-
-#define DEBUG_STATE_MACHINE 0
-#define TSIP_DIALOG_OPTIONS_SIGNAL(self, type, code, phrase, options) \
- tsip_options_event_signal(type, TSIP_DIALOG(self)->ss, code, phrase, options)
-
-/* ======================== internal functions ======================== */
-int send_OPTIONS(tsip_dialog_options_t *self);
-int send_response(tsip_dialog_options_t *self, short status, const char* phrase, const tsip_request_t *request);
-int tsip_dialog_options_OnTerminated(tsip_dialog_options_t *self);
-
-/* ======================== transitions ======================== */
-int tsip_dialog_options_Started_2_Sending_X_sendOPTIONS(va_list *app);
-int tsip_dialog_options_Started_2_Receiving_X_recvOPTIONS(va_list *app);
-int tsip_dialog_options_Sending_2_Sending_X_1xx(va_list *app);
-int tsip_dialog_options_Sending_2_Terminated_X_2xx(va_list *app);
-int tsip_dialog_options_Sending_2_Sending_X_401_407_421_494(va_list *app);
-int tsip_dialog_options_Sending_2_Terminated_X_300_to_699(va_list *app);
-int tsip_dialog_options_Sending_2_Terminated_X_cancel(va_list *app);
-int tsip_dialog_options_Receiving_2_Terminated_X_accept(va_list *app);
-int tsip_dialog_options_Receiving_2_Terminated_X_reject(va_list *app);
-int tsip_dialog_options_Any_2_Terminated_X_transportError(va_list *app);
-int tsip_dialog_options_Any_2_Terminated_X_Error(va_list *app);
-
-/* ======================== conds ======================== */
-
-/* ======================== actions ======================== */
-typedef enum _fsm_action_e
-{
- _fsm_action_sendOPTIONS = tsip_atype_options_send,
- _fsm_action_accept = tsip_atype_accept,
- _fsm_action_reject = tsip_atype_reject,
- _fsm_action_cancel = tsip_atype_cancel,
- _fsm_action_shutdown = tsip_atype_shutdown,
-
- _fsm_action_receiveOPTIONS = 0xFF,
- _fsm_action_1xx,
- _fsm_action_2xx,
- _fsm_action_401_407_421_494,
- _fsm_action_300_to_699,
- _fsm_action_transporterror,
- _fsm_action_error,
-}
-_fsm_action_t;
-
-/* ======================== states ======================== */
-typedef enum _fsm_state_e
-{
- _fsm_state_Started,
- _fsm_state_Sending,
- _fsm_state_Receiving,
- _fsm_state_Terminated
-}
-_fsm_state_t;
-
-
-int tsip_dialog_options_event_callback(const tsip_dialog_options_t *self, tsip_dialog_event_type_t type, const tsip_message_t *msg)
-{
- int ret = -1;
-
- switch(type)
- {
- case tsip_dialog_i_msg:
- {
- if(msg){
- if(TSIP_MESSAGE_IS_RESPONSE(msg)){
- if(TSIP_RESPONSE_IS_1XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_1xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS_2XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_2xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_CODE(msg) == 401 || TSIP_RESPONSE_CODE(msg) == 407 || TSIP_RESPONSE_CODE(msg) == 421 || TSIP_RESPONSE_CODE(msg) == 494){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_401_407_421_494, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS_3456(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_300_to_699, msg, tsk_null);
- }
- else{ /* should never happen */
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_error, msg, tsk_null);
- }
- }
- else if (TSIP_REQUEST_IS_OPTIONS(msg)){ /* have been checked by dialog layer...but */
- // REQUEST ==> Incoming OPTIONS
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_receiveOPTIONS, msg, tsk_null);
- }
- }
- break;
- }
-
- case tsip_dialog_canceled:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_cancel, msg, tsk_null);
- break;
- }
-
- case tsip_dialog_terminated:
- case tsip_dialog_timedout:
- case tsip_dialog_error:
- case tsip_dialog_transport_error:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_transporterror, msg, tsk_null);
- break;
- }
- }
-
- return ret;
-}
-
-tsip_dialog_options_t* tsip_dialog_options_create(const tsip_ssession_handle_t* ss)
-{
- return tsk_object_new(tsip_dialog_options_def_t, ss);
-}
-
-int tsip_dialog_options_init(tsip_dialog_options_t *self)
-{
- //const tsk_param_t* param;
-
- /* Initialize the state machine. */
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Started ===
- */
- // Started -> (send) -> Sending
- TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_sendOPTIONS, _fsm_state_Sending, tsip_dialog_options_Started_2_Sending_X_sendOPTIONS, "tsip_dialog_options_Started_2_Sending_X_sendOPTIONS"),
- // Started -> (receive) -> Receiving
- TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_receiveOPTIONS, _fsm_state_Receiving, tsip_dialog_options_Started_2_Receiving_X_recvOPTIONS, "tsip_dialog_options_Started_2_Receiving_X_recvOPTIONS"),
- // Started -> (Any) -> Started
- TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_dialog_options_Started_2_Started_X_any"),
-
-
- /*=======================
- * === Sending ===
- */
- // Sending -> (1xx) -> Sending
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_1xx, _fsm_state_Sending, tsip_dialog_options_Sending_2_Sending_X_1xx, "tsip_dialog_options_Sending_2_Sending_X_1xx"),
- // Sending -> (2xx) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_2xx, _fsm_state_Terminated, tsip_dialog_options_Sending_2_Terminated_X_2xx, "tsip_dialog_options_Sending_2_Terminated_X_2xx"),
- // Sending -> (401/407/421/494) -> Sending
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_401_407_421_494, _fsm_state_Sending, tsip_dialog_options_Sending_2_Sending_X_401_407_421_494, "tsip_dialog_options_Sending_2_Sending_X_401_407_421_494"),
- // Sending -> (300_to_699) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_300_to_699, _fsm_state_Terminated, tsip_dialog_options_Sending_2_Terminated_X_300_to_699, "tsip_dialog_options_Sending_2_Terminated_X_300_to_699"),
- // Sending -> (cancel) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Sending, _fsm_action_cancel, _fsm_state_Terminated, tsip_dialog_options_Sending_2_Terminated_X_cancel, "tsip_dialog_options_Sending_2_Terminated_X_cancel"),
- // Sending -> (Any) -> Sending
- TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Sending, "tsip_dialog_options_Sending_2_Sending_X_any"),
-
- /*=======================
- * === Receiving ===
- */
- // Receiving -> (accept) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Receiving, _fsm_action_accept, _fsm_state_Terminated, tsip_dialog_options_Receiving_2_Terminated_X_accept, "tsip_dialog_options_Receiving_2_Terminated_X_accept"),
- // Receiving -> (rejected) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Receiving, _fsm_action_reject, _fsm_state_Terminated, tsip_dialog_options_Receiving_2_Terminated_X_reject, "tsip_dialog_options_Receiving_2_Terminated_X_reject"),
- // Receiving -> (Any) -> Receiving
- TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Receiving, "tsip_dialog_options_Receiving_2_Receiving_X_any"),
-
- /*=======================
- * === Any ===
- */
- // Any -> (transport error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_dialog_options_Any_2_Terminated_X_transportError, "tsip_dialog_options_Any_2_Terminated_X_transportError"),
- // Any -> (transport error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_dialog_options_Any_2_Terminated_X_Error, "tsip_dialog_options_Any_2_Terminated_X_Error"),
-
- TSK_FSM_ADD_NULL());
-
- TSIP_DIALOG(self)->callback = TSIP_DIALOG_EVENT_CALLBACK_F(tsip_dialog_options_event_callback);
-
- return 0;
-}
-
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-
-/* Started -> (sendOPTIONS) -> Sending
-*/
-int tsip_dialog_options_Started_2_Sending_X_sendOPTIONS(va_list *app)
-{
- tsip_dialog_options_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_options_t *);
- /*tsip_request_t *request =*/ va_arg(*app, tsip_request_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- TSIP_DIALOG(self)->running = tsk_true;
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connecting, "Dialog connecting");
-
- return send_OPTIONS(self);
-}
-
-/* Started -> (recvOPTIONS) -> Receiving
-*/
-int tsip_dialog_options_Started_2_Receiving_X_recvOPTIONS(va_list *app)
-{
- tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);
- const tsip_request_t *request = va_arg(*app, const tsip_request_t *);
-
- /* Alert the user. */
- TSIP_DIALOG_OPTIONS_SIGNAL(self, tsip_i_options,
- tsip_event_code_dialog_request_incoming, "Incoming Request.", request);
-
- return send_response(self, 200, "OK", request); // Wait for accept
-}
-
-/* Sending -> (1xx) -> Sending
-*/
-int tsip_dialog_options_Sending_2_Sending_X_1xx(va_list *app)
-{
- /*tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);*/
- /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/
-
- return 0;
-}
-
-/* Sending -> (2xx) -> Sending
-*/
-int tsip_dialog_options_Sending_2_Terminated_X_2xx(va_list *app)
-{
- tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* Alert the user. */
- TSIP_DIALOG_OPTIONS_SIGNAL(self, tsip_ao_options,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- /* Reset curr action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), tsk_null);
-
- return 0;
-}
-
-/* Sending -> (401/407/421/494) -> Sending
-*/
-int tsip_dialog_options_Sending_2_Sending_X_401_407_421_494(va_list *app)
-{
- /*tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);*/
- /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/
-
- return 0;
-}
-
-/* Sending -> (300 to 699) -> Terminated
-*/
-int tsip_dialog_options_Sending_2_Terminated_X_300_to_699(va_list *app)
-{
- tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* Alert the user. */
- TSIP_DIALOG_OPTIONS_SIGNAL(self, tsip_ao_options,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return 0;
-}
-
-/* Sending -> (cancel) -> Terminated
-*/
-int tsip_dialog_options_Sending_2_Terminated_X_cancel(va_list *app)
-{
- int ret;
-
- tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);
- /* const tsip_message_t *message = va_arg(*app, const tsip_message_t *); */
-
- /* RFC 3261 - 9.1 Client Behavior
- A CANCEL request SHOULD NOT be sent to cancel a request other than INVITE.
- */
-
- /* Cancel all transactions associated to this dialog (will also be done when the dialog is destroyed (worth nothing)) */
- ret = tsip_transac_layer_cancel_by_dialog(TSIP_DIALOG_GET_STACK(self)->layer_transac, TSIP_DIALOG(self));
-
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_request_cancelled, "Registration cancelled");
-
- return ret;
-}
-
-/* Receiving -> (accept) -> Terminated
-*/
-int tsip_dialog_options_Receiving_2_Terminated_X_accept(va_list *app)
-{
- /*tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);*/
- /**const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/
-
- return 0;
-}
-
-/* Receiving -> (reject) -> Terminated
-*/
-int tsip_dialog_options_Receiving_2_Terminated_X_reject(va_list *app)
-{
- /*tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);*/
- /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/
-
- return 0;
-}
-
-/* Any -> (transport error) -> Terminated
-*/
-int tsip_dialog_options_Any_2_Terminated_X_transportError(va_list *app)
-{
- /*tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);*/
- /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/
-
- return 0;
-}
-
-/* Any -> (error) -> Terminated
-*/
-int tsip_dialog_options_Any_2_Terminated_X_Error(va_list *app)
-{
- /*tsip_dialog_options_t *self = va_arg(*app, tsip_dialog_options_t *);*/
- /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/
-
- return 0;
-}
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-int send_OPTIONS(tsip_dialog_options_t *self)
-{
- tsip_request_t* request = tsk_null;
- int ret = -1;
-
- if(!self){
- return -1;
- }
-
- if(!(request = tsip_dialog_request_new(TSIP_DIALOG(self), "OPTIONS"))){
- return -2;
- }
-
- /* action parameters and payload*/
- if(TSIP_DIALOG(self)->curr_action){
- const tsk_list_item_t* item;
- tsk_list_foreach(item, TSIP_DIALOG(self)->curr_action->headers){
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_DUMMY_VA_ARGS(TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value));
- }
- if(TSIP_DIALOG(self)->curr_action->payload){
- tsip_message_add_content(request, tsk_null, TSK_BUFFER_DATA(TSIP_DIALOG(self)->curr_action->payload), TSK_BUFFER_SIZE(TSIP_DIALOG(self)->curr_action->payload));
- }
- }
-
- ret = tsip_dialog_request_send(TSIP_DIALOG(self), request);
- TSK_OBJECT_SAFE_FREE(request);
-
- return ret;
-}
-
-int send_response(tsip_dialog_options_t *self, short status, const char* phrase, const tsip_request_t *request)
-{
- tsip_response_t *response;
- int ret = -1;
-
- response = tsip_dialog_response_new(TSIP_DIALOG(self), status, phrase, request);
- if(response){
- if(response->To && !response->To->tag){
- tsk_istr_t tag;
- tsk_strrandom(&tag);
- response->To->tag = tsk_strdup(tag);
- }
- ret = tsip_dialog_response_send(TSIP_DIALOG(self), response);
- TSK_OBJECT_SAFE_FREE(response);
- }
-
- return ret;
-}
-
-
-int tsip_dialog_options_OnTerminated(tsip_dialog_options_t *self)
-{
- TSK_DEBUG_INFO("=== OPTIONS Dialog terminated ===");
-
- /* alert user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminated,
- TSIP_DIALOG(self)->lasterror ? TSIP_DIALOG(self)->lasterror : "Dialog terminated");
-
- /* Remove from the dialog layer. */
- return tsip_dialog_remove(TSIP_DIALOG(self));
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-//========================================================
-// SIP dialog OPTIONS object definition
-//
-static tsk_object_t* tsip_dialog_options_ctor(tsk_object_t * self, va_list * app)
-{
- tsip_dialog_options_t *dialog = self;
- if(dialog){
- tsip_ssession_handle_t *ss = va_arg(*app, tsip_ssession_handle_t *);
-
- /* Initialize base class */
- tsip_dialog_init(TSIP_DIALOG(self), tsip_dialog_OPTIONS, tsk_null, ss, _fsm_state_Started, _fsm_state_Terminated);
-
- /* FSM */
- TSIP_DIALOG_GET_FSM(self)->debug = DEBUG_STATE_MACHINE;
- tsk_fsm_set_callback_terminated(TSIP_DIALOG_GET_FSM(self), TSK_FSM_ONTERMINATED_F(tsip_dialog_options_OnTerminated), (const void*)dialog);
-
- /* Initialize the class itself */
- tsip_dialog_options_init(self);
- }
- return self;
-}
-
-static tsk_object_t* tsip_dialog_options_dtor(tsk_object_t * self)
-{
- tsip_dialog_options_t *dialog = self;
- if(dialog){
-
- /* DeInitialize base class (will cancel all transactions) */
- tsip_dialog_deinit(TSIP_DIALOG(self));
-
- TSK_DEBUG_INFO("*** OPTIONS Dialog destroyed ***");
- }
- return self;
-}
-
-static int tsip_dialog_options_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
-{
- return tsip_dialog_cmp(obj1, obj2);
-}
-
-static const tsk_object_def_t tsip_dialog_options_def_s =
-{
- sizeof(tsip_dialog_options_t),
- tsip_dialog_options_ctor,
- tsip_dialog_options_dtor,
- tsip_dialog_options_cmp,
-};
-const tsk_object_def_t *tsip_dialog_options_def_t = &tsip_dialog_options_def_s;
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_publish.client.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_publish.client.c
deleted file mode 100644
index 3a598f3..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_publish.client.c
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_publish.client.c
- * @brief SIP dialog PUBLISH as per RFC 3903.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_publish.h"
-
-#include "tinysip/headers/tsip_header_Dummy.h"
-#include "tinysip/headers/tsip_header_Min_Expires.h"
-#include "tinysip/headers/tsip_header_SIP_ETag.h"
-#include "tinysip/headers/tsip_header_SIP_If_Match.h"
-
-#include "tinysip/transactions/tsip_transac_layer.h"
-
-#include "tinysip/tsip_message.h"
-
-#include "tinysip/api/tsip_api_publish.h"
-
-#include "tsk_debug.h"
-#include "tsk_time.h"
-
-#define DEBUG_STATE_MACHINE 0
-#define TSIP_DIALOG_PUBLISH_TIMER_SCHEDULE(TX) TSIP_DIALOG_TIMER_SCHEDULE(publish, TX)
-#define TSIP_DIALOG_PUBLISH_SIGNAL(self, type, code, phrase, message) \
- tsip_publish_event_signal(type, TSIP_DIALOG(self)->ss, code, phrase, message)
-
-/* ======================== internal functions ======================== */
-int send_PUBLISH(tsip_dialog_publish_t *self);
-int tsip_dialog_publish_OnTerminated(tsip_dialog_publish_t *self);
-
-/* ======================== transitions ======================== */
-int tsip_dialog_publish_Started_2_Trying_X_publish(va_list *app);
-int tsip_dialog_publish_Trying_2_Trying_X_1xx(va_list *app);
-int tsip_dialog_publish_Trying_2_Terminated_X_2xx(va_list *app);
-int tsip_dialog_publish_Trying_2_Connected_X_2xx(va_list *app);
-int tsip_dialog_publish_Trying_2_Trying_X_401_407_421_494(va_list *app);
-int tsip_dialog_publish_Trying_2_Trying_X_423(va_list *app);
-int tsip_dialog_publish_Trying_2_Terminated_X_300_to_699(va_list *app);
-int tsip_dialog_publish_Trying_2_Terminated_X_cancel(va_list *app);
-int tsip_dialog_publish_Connected_2_Trying_X_publish(va_list *app);
-int tsip_dialog_publish_Any_2_Trying_X_hangup(va_list *app);
-int tsip_dialog_publish_Any_2_Trying_X_shutdown(va_list *app);
-int tsip_dialog_publish_Any_2_Terminated_X_transportError(va_list *app);
-int tsip_dialog_publish_Any_2_Terminated_X_Error(va_list *app);
-
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_unpublishing(tsip_dialog_publish_t* dialog, tsip_message_t* message)
-{
- return dialog->unpublishing;
-}
-static tsk_bool_t _fsm_cond_publishing(tsip_dialog_publish_t* dialog, tsip_message_t* message)
-{
- return !_fsm_cond_unpublishing(dialog, message);
-}
-
-static tsk_bool_t _fsm_cond_silent_hangup(tsip_dialog_publish_t* dialog, tsip_message_t* message)
-{
- return TSIP_DIALOG(dialog)->ss->silent_hangup;
-}
-static tsk_bool_t _fsm_cond_not_silent_hangup(tsip_dialog_publish_t* dialog, tsip_message_t* message)
-{
- return !TSIP_DIALOG(dialog)->ss->silent_hangup;
-}
-#define _fsm_cond_silent_shutdown _fsm_cond_silent_hangup
-#define _fsm_cond_not_silent_shutdown _fsm_cond_not_silent_hangup
-
-
-/* ======================== actions ======================== */
-typedef enum _fsm_action_e
-{
- _fsm_action_publish = tsip_atype_publish,
- _fsm_action_cancel = tsip_atype_cancel,
- _fsm_action_hangup = tsip_atype_unpublish,
- _fsm_action_shutdown = tsip_atype_shutdown,
-
- _fsm_action_1xx = 0xFF,
- _fsm_action_2xx,
- _fsm_action_401_407_421_494,
- _fsm_action_423,
- _fsm_action_300_to_699,
- _fsm_action_shutdown_timedout, /* Any -> Terminated */
- _fsm_action_transporterror,
- _fsm_action_error,
-}
-_fsm_action_t;
-
-/* ======================== states ======================== */
-typedef enum _fsm_state_e
-{
- _fsm_state_Started,
- _fsm_state_Trying,
- _fsm_state_Connected,
- _fsm_state_Terminated
-}
-_fsm_state_t;
-
-
-/**
- * Callback function called to alert the dialog for new events from the transaction/transport layers.
- *
- * @param [in,out] self A reference to the dialog.
- * @param type The event type.
- * @param [in,out] msg The incoming SIP/IMS message.
- *
- * @return Zero if succeed and non-zero error code otherwise.
-**/
-int tsip_dialog_publish_event_callback(const tsip_dialog_publish_t *self, tsip_dialog_event_type_t type, const tsip_message_t *msg)
-{
- int ret = -1;
-
- switch(type)
- {
- case tsip_dialog_i_msg:
- {
- if(msg && TSIP_MESSAGE_IS_RESPONSE(msg))
- {
- //
- // RESPONSE
- //
- if(TSIP_RESPONSE_IS_1XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_1xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS_2XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_2xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS(msg,401) || TSIP_RESPONSE_IS(msg,407) || TSIP_RESPONSE_IS(msg,421) || TSIP_RESPONSE_IS(msg,494)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_401_407_421_494, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS(msg,423)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_423, msg, tsk_null);
- }
- else{
- // Alert User
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_error, msg, tsk_null);
- /* TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); */
- }
- }
- else
- {
- //
- // REQUEST
- //
- }
- break;
- }
-
- case tsip_dialog_canceled:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_cancel, msg, tsk_null);
- break;
- }
-
- case tsip_dialog_terminated:
- case tsip_dialog_timedout:
- case tsip_dialog_error:
- case tsip_dialog_transport_error:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_transporterror, msg, tsk_null);
- break;
- }
- }
-
- return ret;
-}
-
-/**
- * Timer manager callback.
- *
- * @param [in,out] self The owner of the signaled timer.
- * @param timer_id The identifier of the signaled timer.
- *
- * @return Zero if succeed and non-zero error code otherwise.
-**/
-int tsip_dialog_publish_timer_callback(const tsip_dialog_publish_t* self, tsk_timer_id_t timer_id)
-{
- int ret = -1;
-
- if(self)
- {
- if(timer_id == self->timerrefresh.id){
- tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_publish, tsk_null, tsk_null);
- ret = 0;
- }
- else if(timer_id == self->timershutdown.id){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_error, tsk_null, tsk_null);
- }
- }
- return ret;
-}
-
-
-tsip_dialog_publish_t* tsip_dialog_publish_create(const tsip_ssession_handle_t* ss)
-{
- return tsk_object_new(tsip_dialog_publish_def_t, ss);
-}
-
-/**
- * Initializes the dialog.
- *
- * @param [in,out] self The dialog to initialize.
-**/
-int tsip_dialog_publish_init(tsip_dialog_publish_t *self)
-{
- /* Initialize the State Machine. */
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Started ===
- */
- // Started -> (PUBLISH) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_publish, _fsm_state_Trying, tsip_dialog_publish_Started_2_Trying_X_publish, "tsip_dialog_publish_Started_2_Trying_X_publish"),
- // Started -> (Any) -> Started
- TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_dialog_publish_Started_2_Started_X_any"),
-
-
- /*=======================
- * === Trying ===
- */
- // Trying -> (1xx) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_1xx, _fsm_state_Trying, tsip_dialog_publish_Trying_2_Trying_X_1xx, "tsip_dialog_publish_Trying_2_Trying_X_1xx"),
- // Trying -> (2xx) -> Terminated
- TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_2xx, _fsm_cond_unpublishing, _fsm_state_Terminated, tsip_dialog_publish_Trying_2_Terminated_X_2xx, "tsip_dialog_publish_Trying_2_Terminated_X_2xx"),
- // Trying -> (2xx) -> Connected
- TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_2xx, _fsm_cond_publishing, _fsm_state_Connected, tsip_dialog_publish_Trying_2_Connected_X_2xx, "tsip_dialog_publish_Trying_2_Connected_X_2xx"),
- // Trying -> (401/407/421/494) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_401_407_421_494, _fsm_state_Trying, tsip_dialog_publish_Trying_2_Trying_X_401_407_421_494, "tsip_dialog_publish_Trying_2_Trying_X_401_407_421_494"),
- // Trying -> (423) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_423, _fsm_state_Trying, tsip_dialog_publish_Trying_2_Trying_X_423, "tsip_dialog_publish_Trying_2_Trying_X_423"),
- // Trying -> (300_to_699) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_300_to_699, _fsm_state_Terminated, tsip_dialog_publish_Trying_2_Terminated_X_300_to_699, "tsip_dialog_publish_Trying_2_Terminated_X_300_to_699"),
- // Trying -> (cancel) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_cancel, _fsm_state_Terminated, tsip_dialog_publish_Trying_2_Terminated_X_cancel, "tsip_dialog_publish_Trying_2_Terminated_X_cancel"),
- // Trying -> (hangup) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_hangup, _fsm_state_Terminated, tsk_null, "tsip_dialog_publish_Trying_2_Terminated_X_hangup"),
- // Trying -> (shutdown) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_shutdown, _fsm_state_Terminated, tsk_null, "tsip_dialog_publish_Trying_2_Terminated_X_shutdown"),
- // Trying -> (Any) -> Trying
- // TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Trying, "tsip_dialog_publish_Trying_2_Trying_X_any"),
-
-
- /*=======================
- * === Connected ===
- */
- // Connected -> (PUBLISH) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_publish, _fsm_state_Trying, tsip_dialog_publish_Connected_2_Trying_X_publish, "tsip_dialog_publish_Connected_2_Trying_X_publish"),
-
- /*=======================
- * === Any ===
- */
- // Any -> (transport error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_dialog_publish_Any_2_Terminated_X_transportError, "tsip_dialog_publish_Any_2_Terminated_X_transportError"),
- // Any -> (error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_dialog_publish_Any_2_Terminated_X_Error, "tsip_dialog_publish_Any_2_Terminated_X_Error"),
- // Any -> (hangup) -> Trying
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_hangup, _fsm_cond_not_silent_hangup, _fsm_state_Trying, tsip_dialog_publish_Any_2_Trying_X_hangup, "tsip_dialog_publish_Any_2_Trying_X_hangup"),
- // Any -> (silenthangup) -> Terminated
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_hangup, _fsm_cond_silent_hangup, _fsm_state_Terminated, tsk_null, "tsip_dialog_publish_Any_2_Trying_X_silenthangup"),
- // Any -> (shutdown) -> Trying
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_shutdown, _fsm_cond_not_silent_shutdown, _fsm_state_Trying, tsip_dialog_publish_Any_2_Trying_X_shutdown, "tsip_dialog_publish_Any_2_Trying_X_shutdown"),
- // Any -> (silentshutdown) -> Terminated
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_shutdown, _fsm_cond_silent_shutdown, _fsm_state_Terminated, tsk_null, "tsip_dialog_publishe_Any_2_Trying_X_silentshutdown"),
- // Any -> (shutdown timedout) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_shutdown_timedout, _fsm_state_Terminated, tsk_null, "tsip_dialog_publish_shutdown_timedout"),
-
- TSK_FSM_ADD_NULL());
-
- /* Sets callback function */
- TSIP_DIALOG(self)->callback = TSIP_DIALOG_EVENT_CALLBACK_F(tsip_dialog_publish_event_callback);
-
- /* Timers */
- self->timerrefresh.id = TSK_INVALID_TIMER_ID;
- self->timerrefresh.timeout = TSIP_DIALOG(self)->expires;
- self->timershutdown.id = TSK_INVALID_TIMER_ID;
- self->timershutdown.timeout = TSIP_DIALOG_SHUTDOWN_TIMEOUT;
-
- return 0;
-}
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-
-/* Started -> (send) -> Trying
-*/
-int tsip_dialog_publish_Started_2_Trying_X_publish(va_list *app)
-{
- tsip_dialog_publish_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_publish_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- TSIP_DIALOG(self)->running = tsk_true;
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connecting, "Dialog connecting");
-
- return send_PUBLISH(self);
-}
-
-/* Trying -> (1xx) -> Trying
-*/
-int tsip_dialog_publish_Trying_2_Trying_X_1xx(va_list *app)
-{
- /*tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);*/
- /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/
-
- return 0;
-}
-
-/* Trying -> (2xx) -> Terminated
-*/
-int tsip_dialog_publish_Trying_2_Terminated_X_2xx(va_list *app)
-{
- tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* Alert the user. */
- TSIP_DIALOG_PUBLISH_SIGNAL(self, self->unpublishing ? tsip_ao_unpublish : tsip_ao_publish,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return 0;
-}
-
-/* Trying -> (2xx) -> Connected
-*/
-int tsip_dialog_publish_Trying_2_Connected_X_2xx(va_list *app)
-{
- tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
- int ret;
-
- tsk_bool_t first_time_to_connect = (TSIP_DIALOG(self)->state == tsip_initial);
-
- /* RFC 3903 - 4.1. Identification of Published Event State
- For each successful PUBLISH request, the ESC will generate and assign
- an entity-tag and return it in the SIP-ETag header field of the 2xx
- response.
- */
- const tsip_header_SIP_ETag_t *SIP_ETag;
- if((SIP_ETag = (const tsip_header_SIP_ETag_t*)tsip_message_get_header(response, tsip_htype_SIP_ETag))){
- tsk_strupdate(&self->etag, SIP_ETag->value);
- }
-
- /* Alert the user (session)*/
- TSIP_DIALOG_PUBLISH_SIGNAL(self, self->unpublishing ? tsip_ao_unpublish : tsip_ao_publish,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- /* Alert the user (dialog)*/
- if(first_time_to_connect){ /* PUBLISH not dialog oriented ...but */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connected, "Dialog connected");
- }
-
- /* Update the dialog state */
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), response))){
- return ret;
- }
-
- /* Reset current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), tsk_null);
-
- /* Request timeout for dialog refresh (re-publish). */
- self->timerrefresh.timeout = tsip_dialog_get_newdelay(TSIP_DIALOG(self), response);
- TSIP_DIALOG_PUBLISH_TIMER_SCHEDULE(refresh);
-
- return 0;
-}
-
-/* Trying -> (401/407/421/494) -> Trying
-*/
-int tsip_dialog_publish_Trying_2_Trying_X_401_407_421_494(va_list *app)
-{
- tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
- int ret;
-
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), response))){
- /* Alert the user. */
- TSIP_DIALOG_PUBLISH_SIGNAL(self, self->unpublishing ? tsip_ao_unpublish : tsip_ao_publish,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return ret;
- }
-
- return send_PUBLISH(self);
-}
-
-/* Trying -> (423) -> Trying
-*/
-int tsip_dialog_publish_Trying_2_Trying_X_423(va_list *app)
-{
- tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- tsip_header_Min_Expires_t *hdr;
-
- /*
- RFC 3261 - 10.2.8 Error Responses
-
- If a UA receives a 423 (Interval Too Brief) response, it MAY retry
- the registration after making the expiration interval of all contact
- addresses in the PUBLISH request equal to or greater than the
- expiration interval within the Min-Expires header field of the 423
- (Interval Too Brief) response.
- */
- hdr = (tsip_header_Min_Expires_t*)tsip_message_get_header(response, tsip_htype_Min_Expires);
- if(hdr){
- TSIP_DIALOG(self)->expires = TSK_TIME_S_2_MS(hdr->value);
- send_PUBLISH(self);
- }
- else{
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_message_error, "Received invalid SIP response");
-
- return -1;
- }
-
- return 0;
-}
-
-/* Trying -> (300 to 699) -> Terminated
-*/
-int tsip_dialog_publish_Trying_2_Terminated_X_300_to_699(va_list *app)
-{
- tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), TSIP_RESPONSE_PHRASE(response));
-
- /* Alert the user. */
- TSIP_DIALOG_PUBLISH_SIGNAL(self, self->unpublishing ? tsip_ao_unpublish : tsip_ao_publish,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return 0;
-}
-
-/* Trying -> (cancel) -> Terminated
-*/
-int tsip_dialog_publish_Trying_2_Terminated_X_cancel(va_list *app)
-{
- int ret;
- tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);
- /* const tsip_message_t *message = va_arg(*app, const tsip_message_t *); */
-
- /* Cancel all transactions associated to this dialog (will also be done when the dialog is destroyed (worth nothing)) */
- ret = tsip_transac_layer_cancel_by_dialog(TSIP_DIALOG_GET_STACK(self)->layer_transac, TSIP_DIALOG(self));
-
- /* RFC 3261 - 9.1 Client Behavior
- A CANCEL request SHOULD NOT be sent to cancel a request other than INVITE.
- */
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_request_cancelled, "Subscription cancelled");
-
- return ret;
-}
-
-/* Connected -> (PUBLISH) -> Trying
-*/
-int tsip_dialog_publish_Connected_2_Trying_X_publish(va_list *app)
-{
- tsip_dialog_publish_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_publish_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* Set current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- return send_PUBLISH(self);
-}
-
-/* Connected -> (hangup) -> Trying
-*/
-int tsip_dialog_publish_Any_2_Trying_X_hangup(va_list *app)
-{
- tsip_dialog_publish_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_publish_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* Set current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminating, "Terminating dialog");
-
- self->unpublishing = tsk_true;
- return send_PUBLISH(self);
-}
-
-/* Any -> (shutdown) -> Trying
-*/
-int tsip_dialog_publish_Any_2_Trying_X_shutdown(va_list *app)
-{
- tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);
-
- /* schedule shutdow timeout */
- TSIP_DIALOG_PUBLISH_TIMER_SCHEDULE(shutdown);
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminating, "Terminating dialog");
-
- self->unpublishing = tsk_true;
- return send_PUBLISH(self);
-}
-
-/* Any -> (transport error) -> Terminated
-*/
-int tsip_dialog_publish_Any_2_Terminated_X_transportError(va_list *app)
-{
- tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);
- /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/
-
- /* Alert the user. */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_transport_error, "Transport error.");
-
- return 0;
-}
-
-/* Any -> (Error) -> Terminated
-*/
-int tsip_dialog_publish_Any_2_Terminated_X_Error(va_list *app)
-{
- tsip_dialog_publish_t *self = va_arg(*app, tsip_dialog_publish_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* Alert the user. */
- if(response){
- TSIP_DIALOG_PUBLISH_SIGNAL(self, self->unpublishing ? tsip_ao_unpublish : tsip_ao_publish,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- }
- else{
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_global_error, "Global error.");
- }
-
- return 0;
-}
-
-
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-
-/**
- * Sends a PUBLISH request.
-**/
-int send_PUBLISH(tsip_dialog_publish_t *self)
-{
- tsip_request_t *request = tsk_null;
- int ret = -1;
- const tsip_action_t* action;
-
- if(!self){
- return -1;
- }
-
- // action
- action = TSIP_DIALOG(self)->curr_action;
-
- if(self->unpublishing){
- TSIP_DIALOG(self)->expires = 0;
- }
-
- /* RFC 3903 - 4.1. Identification of Published Event State
- The presence of a body and the SIP-If-Match header field determine
- the specific SSESSION that the request is performing, as described in Table 1.
- +-----------+-------+---------------+---------------+
- | SSESSION | Body? | SIP-If-Match? | Expires Value |
- +-----------+-------+---------------+---------------+
- | Initial | yes | no | > 0 |
- | Refresh | no | yes | > 0 |
- | Modify | yes | yes | > 0 |
- | Remove | no | yes | 0 |
- +-----------+-------+---------------+---------------+
- Table 1: Publication ssessions
- */
- if((request = tsip_dialog_request_new(TSIP_DIALOG(self), "PUBLISH"))){
- /*Etag. If initial then etag is null. */
- if(self->etag){
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_SIP_IF_MATCH_VA_ARGS(self->etag));
- }
- /*Body*/
- if(action && action->payload && !self->unpublishing){
- const tsk_list_item_t* item;
- tsk_list_foreach(item, action->headers){
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_DUMMY_VA_ARGS(TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value));
- }
- if(action->payload){
- tsip_message_add_content(request, tsk_null, TSK_BUFFER_DATA(action->payload), TSK_BUFFER_SIZE(action->payload));
- }
- }
-
- ret = tsip_dialog_request_send(TSIP_DIALOG(self), request);
- TSK_OBJECT_SAFE_FREE(request);
- }
-
- return ret;
-}
-
-/**
- * Callback function called by the state machine manager to signal that the final state has been reached.
- *
- * @param [in,out] self The state machine owner.
-**/
-int tsip_dialog_publish_OnTerminated(tsip_dialog_publish_t *self)
-{
- TSK_DEBUG_INFO("=== PUBLISH Dialog terminated ===");
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminated,
- TSIP_DIALOG(self)->lasterror ? TSIP_DIALOG(self)->lasterror : "Dialog terminated");
-
- /* Remove from the dialog layer. */
- return tsip_dialog_remove(TSIP_DIALOG(self));
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-//========================================================
-// SIP dialog PUBLISH object definition
-//
-static tsk_object_t* tsip_dialog_publish_ctor(tsk_object_t * self, va_list * app)
-{
- tsip_dialog_publish_t *dialog = self;
- if(dialog){
- tsip_ssession_handle_t *ss = va_arg(*app, tsip_ssession_handle_t *);
-
- /* init base class */
- tsip_dialog_init(TSIP_DIALOG(self), tsip_dialog_PUBLISH, tsk_null, ss, _fsm_state_Started, _fsm_state_Terminated);
-
- /* FSM */
- TSIP_DIALOG_GET_FSM(self)->debug = DEBUG_STATE_MACHINE;
- tsk_fsm_set_callback_terminated(TSIP_DIALOG_GET_FSM(self), TSK_FSM_ONTERMINATED_F(tsip_dialog_publish_OnTerminated), (const void*)dialog);
-
- /* init the class itself */
- tsip_dialog_publish_init(self);
- }
- return self;
-}
-
-static tsk_object_t* tsip_dialog_publish_dtor(tsk_object_t * _self)
-{
- tsip_dialog_publish_t *self = _self;
- if(self){
- TSK_DEBUG_INFO("*** PUBLISH Dialog destroyed ***");
-
- /* Cancel all timers */
- TSIP_DIALOG_TIMER_CANCEL(refresh);
- TSIP_DIALOG_TIMER_CANCEL(shutdown);
-
- /* deinit base class (will cancel all transactions) */
- tsip_dialog_deinit(TSIP_DIALOG(self));
-
- /* deinit self*/
- TSK_FREE(self->etag);
- }
- return self;
-}
-
-static int tsip_dialog_publish_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
-{
- return tsip_dialog_cmp(obj1, obj2);
-}
-
-static const tsk_object_def_t tsip_dialog_publish_def_s =
-{
- sizeof(tsip_dialog_publish_t),
- tsip_dialog_publish_ctor,
- tsip_dialog_publish_dtor,
- tsip_dialog_publish_cmp,
-};
-const tsk_object_def_t *tsip_dialog_publish_def_t = &tsip_dialog_publish_def_s;
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.c
deleted file mode 100644
index 5102b86..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.c
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-#include "tinysip/dialogs/tsip_dialog_register.h"
-#include "tinysip/dialogs/tsip_dialog_register.common.h"
-
-#include "tinysip/parsers/tsip_parser_uri.h"
-
-#include "tinysip/transports/tsip_transport_layer.h"
-
-#include "tinysip/headers/tsip_header_Dummy.h"
-#include "tinysip/headers/tsip_header_Supported.h"
-
-#include "tinysip/transactions/tsip_transac_layer.h"
-
-#include "tsk_memory.h"
-#include "tsk_debug.h"
-#include "tsk_time.h"
-
-
-/* ======================== internal functions ======================== */
-int tsip_dialog_register_send_REGISTER(tsip_dialog_register_t *self, tsk_bool_t initial);
-int tsip_dialog_register_send_RESPONSE(tsip_dialog_register_t *self, const tsip_request_t* request, short code, const char* phrase);
-int tsip_dialog_register_OnTerminated(tsip_dialog_register_t *self);
-
-/* ======================== transitions ======================== */
-int tsip_dialog_register_Any_2_InProgress_X_hangup(va_list *app);
-int tsip_dialog_register_Any_2_InProgress_X_shutdown(va_list *app);
-int tsip_dialog_register_Any_2_Terminated_X_transportError(va_list *app);
-int tsip_dialog_register_Any_2_Terminated_X_Error(va_list *app);
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_silent_hangup(tsip_dialog_register_t* dialog, tsip_message_t* message)
-{
- return TSIP_DIALOG(dialog)->ss->silent_hangup;
-}
-static tsk_bool_t _fsm_cond_not_silent_hangup(tsip_dialog_register_t* dialog, tsip_message_t* message)
-{
- return !TSIP_DIALOG(dialog)->ss->silent_hangup;
-}
-
-
-/* Client-Side dialog */
-extern int tsip_dialog_register_client_init(tsip_dialog_register_t *self);
-/* Server-Side dialog */
-extern int tsip_dialog_register_server_init(tsip_dialog_register_t *self);
-
-/**
- * @fn int tsip_dialog_register_event_callback(const tsip_dialog_register_t *self, tsip_dialog_event_type_t type,
- * const tsip_message_t *msg)
- *
- * @brief Callback function called to alert the dialog for new events from the transaction/transport layers.
- *
- * @param [in,out] self A reference to the dialog.
- * @param type The event type.
- * @param [in,out] msg The incoming SIP/IMS message.
- *
- * @return Zero if succeed and non-zero error code otherwise.
-**/
-int tsip_dialog_register_event_callback(const tsip_dialog_register_t *self, tsip_dialog_event_type_t type, const tsip_message_t *msg)
-{
- int ret = -1;
-
- switch(type){
-
- case tsip_dialog_i_msg:
- {
- if(msg){
- if(TSIP_MESSAGE_IS_RESPONSE(msg)){
- //
- // RESPONSE
- //
- if(TSIP_RESPONSE_IS_1XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_1xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS_2XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_2xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS(msg,401) || TSIP_RESPONSE_IS(msg,407) || TSIP_RESPONSE_IS(msg,421) || TSIP_RESPONSE_IS(msg,494)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_401_407_421_494, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS(msg,423)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_423, msg, tsk_null);
- }
- else{
- // Alert User
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_error, msg, tsk_null);
- /* TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); */
- }
- }
- else{
- //
- // REQUEST
- //
- if(TSIP_REQUEST_IS_REGISTER(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_iREGISTER, msg, tsk_null);
- }
- }
- }
- break;
- }
-
- case tsip_dialog_canceled:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_cancel, msg, tsk_null);
- break;
- }
-
- case tsip_dialog_terminated:
- case tsip_dialog_timedout:
- case tsip_dialog_error:
- case tsip_dialog_transport_error:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_transporterror, msg, tsk_null);
- break;
- }
- }
-
- return ret;
-}
-
-/**Timer manager callback.
- *
- * @param self The owner of the signaled timer.
- * @param timer_id The identifier of the signaled timer.
- *
- * @return Zero if succeed and non-zero error code otherwise.
-**/
-int tsip_dialog_register_timer_callback(const tsip_dialog_register_t* self, tsk_timer_id_t timer_id)
-{
- int ret = -1;
-
- if(self){
- if(timer_id == self->timerrefresh.id){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_oREGISTER, tsk_null, tsk_null);
- }
- else if(timer_id == self->timershutdown.id){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_shutdown_timedout, tsk_null, tsk_null);
- }
- }
- return ret;
-}
-
-/** Create SIP REGISTER dialog. */
-tsip_dialog_register_t* tsip_dialog_register_create(const tsip_ssession_handle_t* ss, const char* call_id)
-{
- return tsk_object_new(tsip_dialog_register_def_t, ss, call_id);
-}
-
-
-/** Initializes the dialog.
- *
- * @param [in,out] self The dialog to initialize.
-**/
-int tsip_dialog_register_init(tsip_dialog_register_t *self)
-{
- // Initialize client side
- tsip_dialog_register_client_init(self);
- // initialize server side
- tsip_dialog_register_server_init(self);
-
- /* Initialize common side */
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Any ===
- */
- // Any -> (hangup) -> InProgress
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_hangup, _fsm_cond_not_silent_hangup, _fsm_state_InProgress, tsip_dialog_register_Any_2_InProgress_X_hangup, "tsip_dialog_register_Any_2_InProgress_X_hangup"),
- // Any -> (silenthangup) -> Terminated
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_hangup, _fsm_cond_silent_hangup, _fsm_state_Terminated, tsk_null, "tsip_dialog_register_Any_2_InProgress_X_silenthangup"),
- // Any -> (shutdown) -> InProgress
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_shutdown, _fsm_cond_not_silent_shutdown, _fsm_state_InProgress, tsip_dialog_register_Any_2_InProgress_X_shutdown, "tsip_dialog_register_Any_2_InProgress_X_shutdown"),
- // Any -> (silentshutdown) -> Terminated
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_shutdown, _fsm_cond_silent_shutdown, _fsm_state_Terminated, tsk_null, "tsip_dialog_register_Any_2_InProgress_X_silentshutdown"),
- // Any -> (shutdown timedout) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_shutdown_timedout, _fsm_state_Terminated, tsk_null, "tsip_dialog_register_shutdown_timedout"),
- // Any -> (transport error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_dialog_register_Any_2_Terminated_X_transportError, "tsip_dialog_register_Any_2_Terminated_X_transportError"),
- // Any -> (error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_dialog_register_Any_2_Terminated_X_Error, "tsip_dialog_register_Any_2_Terminated_X_Error"),
-
- TSK_FSM_ADD_NULL());
-
- /* Sets callback function */
- TSIP_DIALOG(self)->callback = TSIP_DIALOG_EVENT_CALLBACK_F(tsip_dialog_register_event_callback);
-
- /* Timers */
- self->timerrefresh.id = TSK_INVALID_TIMER_ID;
- self->timerrefresh.timeout = TSIP_DIALOG(self)->expires;
- self->timershutdown.id = TSK_INVALID_TIMER_ID;
- self->timershutdown.timeout = TSIP_DIALOG_SHUTDOWN_TIMEOUT;
-
- return 0;
-}
-
-
-
-
-/* Any -> (hangup) -> InProgress
-*/
-int tsip_dialog_register_Any_2_InProgress_X_hangup(va_list *app)
-{
- tsip_dialog_register_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_register_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* Set current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminating, "Terminating dialog");
-
- self->unregistering = tsk_true;
- return tsip_dialog_register_send_REGISTER(self, tsk_true);
-}
-
-/* Any -> (shutdown) -> InProgress
-*/
-int tsip_dialog_register_Any_2_InProgress_X_shutdown(va_list *app)
-{
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
-
- /* schedule shutdow timeout */
- TSIP_DIALOG_REGISTER_TIMER_SCHEDULE(shutdown);
-
- /* alert user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminating, "Terminating dialog");
-
- self->unregistering = tsk_true;
- return tsip_dialog_register_send_REGISTER(self, tsk_true);
-}
-
-/* Any -> (transport error) -> Terminated
-*/
-int tsip_dialog_register_Any_2_Terminated_X_transportError(va_list *app)
-{
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/
-
- /* Alert the user. */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_transport_error, "Transport error.");
-
- return 0;
-}
-
-/* Any -> (error) -> Terminated
-*/
-int tsip_dialog_register_Any_2_Terminated_X_Error(va_list *app)
-{
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), TSIP_RESPONSE_PHRASE(response));
-
- /* Alert the user. */
- if(response){
- TSIP_DIALOG_REGISTER_SIGNAL(self, self->unregistering ? tsip_ao_unregister : tsip_ao_register,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- }
- else{
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_global_error, "Global error.");
- }
-
- return 0;
-}
-
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-
-/**
- *
- * Sends a REGISTER request.
- *
- * @param [in,out] self The caller.
- * @param [in] initial Indicates whether it's an initial (new CSeq) REGISTER or not.
- * Initial REGISTER request will creates new IPSec temporary SAs.
- *
- * @return Zero if succeed and non-zero error code otherwise.
-**/
-int tsip_dialog_register_send_REGISTER(tsip_dialog_register_t *self, tsk_bool_t initial)
-{
- tsip_request_t *request;
- int ret = -1;
-
- /* whether we are unregistering */
- if(self->unregistering){
- TSIP_DIALOG(self)->expires = 0;
- }
-
- /* creates REGISTER request */
- if((request = tsip_dialog_request_new(TSIP_DIALOG(self), "REGISTER"))){
- /* == RCS phase 2
- */
- /*if(TSIP_DIALOG_GET_STACK(self)->enable_gsmarcs){
- TSIP_HEADER_ADD_PARAM(request->Contact, "+g.oma.sip-im.large-message", 0);
- TSIP_HEADER_ADD_PARAM(request->Contact, "audio", 0);
- TSIP_HEADER_ADD_PARAM(request->Contact, "video", 0);
- TSIP_HEADER_ADD_PARAM(request->Contact, "+g.3gpp.cs-voice", 0);
- TSIP_HEADER_ADD_PARAM(request->Contact, "+g.3gpp.icsi-ref", TSIP_ICSI_QUOTED_MMTEL_PSVOICE);
- }*/
-
- ///* mobility */
- //if(TSIP_DIALOG_GET_STACK(self)->mobility){
- // TSIP_HEADER_ADD_PARAM(request->Contact, "mobility", TSIP_DIALOG_GET_STACK(self)->mobility);
- //}
-
- ///* deviceID - FIXME: find reference. */
- //if(TSIP_DIALOG_GET_STACK(self)->device_id){
- // TSIP_HEADER_ADD_PARAM(request->Contact, "+deviceID", TSIP_DIALOG_GET_STACK(self)->device_id);
- //}
-
- ///* GSMA Image Sharing */
- //if(TSIP_DIALOG_GET_STACK(self)->enable_gsmais){
- // TSIP_HEADER_ADD_PARAM(request->Contact, "+g.3gpp.app_ref", TSIP_IARI_QUOTED_GSMAIS);
- //}
-
- ///* 3GPP TS 24.341 subclause 5.3.2.2 */
- //if(TSIP_DIALOG_GET_STACK(self)->enable_3gppsms){
- // TSIP_HEADER_ADD_PARAM(request->Contact, "+g.3gpp.smsip", 0);
- //}
-
- /* 3GPP TS 24.229 - 5.1.1.2 Initial registration */
- if(TSIP_DIALOG(self)->state ==tsip_initial){
- /*
- g) the Supported header field containing the option-tag "path", and
- 1) if GRUU is supported, the option-tag "gruu"; and
- 2) if multiple registrations is supported, the option-tag "outbound".
- */
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_SUPPORTED_VA_ARGS("path"));
- //if(1==2/* gruu*/){
- //}
- //else if(2 == 3 /* multiple registrations */){
- //}
- }
-
- /* action parameters and payload */
- if(TSIP_DIALOG(self)->curr_action){
- const tsk_list_item_t* item;
- tsk_list_foreach(item, TSIP_DIALOG(self)->curr_action->headers){
- TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_DUMMY_VA_ARGS(TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value));
- }
- if(TSIP_DIALOG(self)->curr_action->payload){
- tsip_message_add_content(request, tsk_null, TSK_BUFFER_DATA(TSIP_DIALOG(self)->curr_action->payload), TSK_BUFFER_SIZE(TSIP_DIALOG(self)->curr_action->payload));
- }
- }
-
- /* Create temorary SAs if initial register. */
- if(TSIP_DIALOG_GET_STACK(self)->security.secagree_mech){
- if(tsk_striequals(TSIP_DIALOG_GET_STACK(self)->security.secagree_mech, "ipsec-3gpp")){
- if(initial){
- tsip_transport_createTempSAs(TSIP_DIALOG_GET_STACK(self)->layer_transport);
- }
- else{
- AKA_CK_T ck;
- AKA_IK_T ik;
- tsip_dialog_getCKIK(TSIP_DIALOG(self), &ck, &ik);
- tsip_transport_startSAs(TSIP_DIALOG_GET_STACK(self)->layer_transport, (const tipsec_key_t*)ik, (const tipsec_key_t*)ck);
- }
- }
- }
-
- if(!(ret = tsip_dialog_request_send(TSIP_DIALOG(self), request))){
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_request_sent, "(un)REGISTER request successfully sent.");
- }
- else{
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_transport_error, "Transport error.");
- }
-
- TSK_OBJECT_SAFE_FREE(request);
- }
-
- return ret;
-}
-
-
-
-// Send any response
-int tsip_dialog_register_send_RESPONSE(tsip_dialog_register_t *self, const tsip_request_t* request, short code, const char* phrase)
-{
- tsip_response_t *response;
- int ret = -1;
-
- if(!self || !request){
- TSK_DEBUG_ERROR("Invalid parameter");
- return 1;
- }
-
- if((response = tsip_dialog_response_new(TSIP_DIALOG(self), code, phrase, request))){
- ret = tsip_dialog_response_send(TSIP_DIALOG(self), response);
- TSK_OBJECT_SAFE_FREE(response);
- }
- return ret;
-}
-
-
-
-/**
- * @fn int tsip_dialog_register_OnTerminated(tsip_dialog_register_t *self)
- *
- * @brief Callback function called by the state machine manager to signal that the final state has been reached.
- *
- * @param [in,out] self The state machine owner.
-**/
-int tsip_dialog_register_OnTerminated(tsip_dialog_register_t *self)
-{
- TSK_DEBUG_INFO("=== REGISTER Dialog terminated ===");
-
- /* Cleanup IPSec SAs */
- if(TSIP_DIALOG_GET_STACK(self)->security.secagree_mech && tsk_striequals(TSIP_DIALOG_GET_STACK(self)->security.secagree_mech, "ipsec-3gpp")){
- tsip_transport_cleanupSAs(TSIP_DIALOG_GET_STACK(self)->layer_transport);
- }
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminated,
- TSIP_DIALOG(self)->lasterror ? TSIP_DIALOG(self)->lasterror : "Dialog terminated");
-
- /* Remove from the dialog layer. */
- return tsip_dialog_remove(TSIP_DIALOG(self));
-}
-
-
-
-
-//========================================================
-// SIP dialog REGISTER object definition
-//
-static tsk_object_t* tsip_dialog_register_ctor(tsk_object_t * self, va_list * app)
-{
- tsip_dialog_register_t *dialog = self;
- if(dialog){
- tsip_ssession_t *ss = va_arg(*app, tsip_ssession_t *);
- const char* call_id = va_arg(*app, const char *);
-
- /* Initialize base class */
- tsip_dialog_init(TSIP_DIALOG(self), tsip_dialog_REGISTER, call_id, ss, _fsm_state_Started, _fsm_state_Terminated);
-
- /* create FSM */
- TSIP_DIALOG_GET_FSM(self)->debug = DEBUG_STATE_MACHINE;
- tsk_fsm_set_callback_terminated(TSIP_DIALOG_GET_FSM(self), TSK_FSM_ONTERMINATED_F(tsip_dialog_register_OnTerminated), (const void*)dialog);
-
- /* Initialize the class itself */
- tsip_dialog_register_init(self);
- }
- return self;
-}
-
-static tsk_object_t* tsip_dialog_register_dtor(tsk_object_t * _self)
-{
- tsip_dialog_register_t *self = _self;
- if(self){
-
- /* Cancel all timers */
- TSIP_DIALOG_TIMER_CANCEL(refresh);
- TSIP_DIALOG_TIMER_CANCEL(shutdown);
-
- /* DeInitialize base class (will cancel all transactions) */
- tsip_dialog_deinit(TSIP_DIALOG(self));
-
- // Delete resources
- TSK_OBJECT_SAFE_FREE(self->last_iRegister);
-
- TSK_DEBUG_INFO("*** REGISTER Dialog destroyed ***");
- }
- return self;
-}
-
-static int tsip_dialog_register_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
-{
- return tsip_dialog_cmp(obj1, obj2);
-}
-
-static const tsk_object_def_t tsip_dialog_register_def_s =
-{
- sizeof(tsip_dialog_register_t),
- tsip_dialog_register_ctor,
- tsip_dialog_register_dtor,
- tsip_dialog_register_cmp,
-};
-const tsk_object_def_t *tsip_dialog_register_def_t = &tsip_dialog_register_def_s;
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.client.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.client.c
deleted file mode 100644
index d1cac10..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.client.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_register.client.c
- * @brief SIP dialog register (Client side).
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_register.h"
-#include "tinysip/dialogs/tsip_dialog_register.common.h"
-
-#include "tinysip/transports/tsip_transport_layer.h"
-#include "tinysip/transactions/tsip_transac_layer.h"
-
-#include "tinysip/headers/tsip_header_Path.h"
-#include "tinysip/headers/tsip_header_Service_Route.h"
-#include "tinysip/headers/tsip_header_P_Associated_URI.h"
-#include "tinysip/headers/tsip_header_Min_Expires.h"
-
-#include "tinysip/parsers/tsip_parser_uri.h"
-
-/* ======================== external functions ======================== */
-extern int tsip_dialog_register_timer_callback(const tsip_dialog_register_t* self, tsk_timer_id_t timer_id);
-extern int tsip_dialog_register_send_REGISTER(tsip_dialog_register_t *self, tsk_bool_t initial);
-
-/* ======================== transitions ======================== */
-int tsip_dialog_register_Started_2_InProgress_X_oRegister(va_list *app);
-int tsip_dialog_register_InProgress_2_InProgress_X_1xx(va_list *app);
-int tsip_dialog_register_InProgress_2_Terminated_X_2xx(va_list *app);
-int tsip_dialog_register_InProgress_2_Connected_X_2xx(va_list *app);
-int tsip_dialog_register_InProgress_2_InProgress_X_401_407_421_494(va_list *app);
-int tsip_dialog_register_InProgress_2_InProgress_X_423(va_list *app);
-int tsip_dialog_register_InProgress_2_Terminated_X_300_to_699(va_list *app);
-int tsip_dialog_register_InProgress_2_Terminated_X_cancel(va_list *app);
-int tsip_dialog_register_Connected_2_InProgress_X_oRegister(va_list *app);
-
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_client_unregistering(tsip_dialog_register_t* dialog, tsip_message_t* message)
-{
- return !dialog->is_server && dialog->unregistering;
-}
-static tsk_bool_t _fsm_cond_client_registering(tsip_dialog_register_t* dialog, tsip_message_t* message)
-{
- return !_fsm_cond_client_unregistering(dialog, message);
-}
-
-
-/** Initializes the dialog.
- *
- * @param [in,out] self The dialog to initialize.
-**/
-int tsip_dialog_register_client_init(tsip_dialog_register_t *self)
-{
- /* Initialize the state machine. */
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Started ===
- */
- // Started -> (REGISTER) -> InProgress
- TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_oREGISTER, _fsm_state_InProgress, tsip_dialog_register_Started_2_InProgress_X_oRegister, "tsip_dialog_register_Started_2_InProgress_X_oRegister"),
- // Started -> (Any) -> Started
- //TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_dialog_register_Started_2_Started_X_any"),
-
-
- /*=======================
- * === InProgress ===
- */
- // InProgress -> (1xx) -> InProgress
- TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_1xx, _fsm_state_InProgress, tsip_dialog_register_InProgress_2_InProgress_X_1xx, "tsip_dialog_register_InProgress_2_InProgress_X_1xx"),
- // InProgress -> (2xx) -> Terminated
- TSK_FSM_ADD(_fsm_state_InProgress, _fsm_action_2xx, _fsm_cond_client_unregistering, _fsm_state_Terminated, tsip_dialog_register_InProgress_2_Terminated_X_2xx, "tsip_dialog_register_InProgress_2_Terminated_X_2xx"),
- // InProgress -> (2xx) -> Connected
- TSK_FSM_ADD(_fsm_state_InProgress, _fsm_action_2xx, _fsm_cond_client_registering, _fsm_state_Connected, tsip_dialog_register_InProgress_2_Connected_X_2xx, "tsip_dialog_register_InProgress_2_Connected_X_2xx"),
- // InProgress -> (401/407/421/494) -> InProgress
- TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_401_407_421_494, _fsm_state_InProgress, tsip_dialog_register_InProgress_2_InProgress_X_401_407_421_494, "tsip_dialog_register_InProgress_2_InProgress_X_401_407_421_494"),
- // InProgress -> (423) -> InProgress
- TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_423, _fsm_state_InProgress, tsip_dialog_register_InProgress_2_InProgress_X_423, "tsip_dialog_register_InProgress_2_InProgress_X_423"),
- // InProgress -> (300_to_699) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_300_to_699, _fsm_state_Terminated, tsip_dialog_register_InProgress_2_Terminated_X_300_to_699, "tsip_dialog_register_InProgress_2_Terminated_X_300_to_699"),
- // InProgress -> (cancel) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_cancel, _fsm_state_Terminated, tsip_dialog_register_InProgress_2_Terminated_X_cancel, "tsip_dialog_register_InProgress_2_Terminated_X_cancel"),
- // InProgress -> (hangup) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_hangup, _fsm_state_Terminated, tsk_null, "tsip_dialog_register_InProgress_2_Terminated_X_hangup"),
- // InProgress -> (shutdown) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_shutdown, _fsm_state_Terminated, tsk_null, "tsip_dialog_register_InProgress_2_Terminated_X_shutdown"),
- // InProgress -> (Any) -> InProgress
- //TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_InProgress, "tsip_dialog_register_InProgress_2_InProgress_X_any"),
-
-
- /*=======================
- * === Connected ===
- */
- // Connected -> (register) -> InProgress [refresh case]
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_oREGISTER, _fsm_state_InProgress, tsip_dialog_register_Connected_2_InProgress_X_oRegister, "tsip_dialog_register_Connected_2_InProgress_X_oRegister"),
-
-
- TSK_FSM_ADD_NULL());
-
- return 0;
-}
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-/* Started -> (REGISTER) -> InProgress
-*/
-int tsip_dialog_register_Started_2_InProgress_X_oRegister(va_list *app)
-{
- tsip_dialog_register_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_register_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- TSIP_DIALOG(self)->running = tsk_true;
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connecting, "Dialog connecting");
-
- return tsip_dialog_register_send_REGISTER(self, tsk_true);
-}
-
-/* InProgress -> (1xx) -> InProgress
-*/
-int tsip_dialog_register_InProgress_2_InProgress_X_1xx(va_list *app)
-{
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* Alert the user (session) */
- TSIP_DIALOG_REGISTER_SIGNAL(self, tsip_ao_register,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return tsip_dialog_update(TSIP_DIALOG(self), response);
-}
-
-/* InProgress -> (2xx) -> Connected
-*/
-//#include "tsk_thread.h"
-int tsip_dialog_register_InProgress_2_Connected_X_2xx(va_list *app)
-{
- int ret;
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- tsk_bool_t first_time_to_connect = (TSIP_DIALOG(self)->state == tsip_initial);
-
- /* - Set P-associated-uriS
- * - Update service-routes
- * - Update Pats
- */
- {
- tsk_size_t index;
- const tsip_header_Path_t *hdr_Path;
- const tsip_header_Service_Route_t *hdr_Service_Route;
- const tsip_header_P_Associated_URI_t *hdr_P_Associated_URI_t;
- tsip_uri_t *uri;
-
- /* To avoid memory leaks ==> delete all concerned objects (it worth nothing) */
- TSK_OBJECT_SAFE_FREE(TSIP_DIALOG_GET_STACK(self)->associated_uris);
- TSK_OBJECT_SAFE_FREE(TSIP_DIALOG_GET_STACK(self)->service_routes);
- TSK_OBJECT_SAFE_FREE(TSIP_DIALOG_GET_STACK(self)->paths);
-
- /* Associated URIs */
- for(index = 0; (hdr_P_Associated_URI_t = (const tsip_header_P_Associated_URI_t*)tsip_message_get_headerAt(response, tsip_htype_P_Associated_URI, index)); index++){
- if(!TSIP_DIALOG_GET_STACK(self)->associated_uris){
- TSIP_DIALOG_GET_STACK(self)->associated_uris = tsk_list_create();
- }
- uri = tsk_object_ref(hdr_P_Associated_URI_t->uri);
- tsk_list_push_back_data(TSIP_DIALOG_GET_STACK(self)->associated_uris, (void**)&uri);
- }
-
- /* Service-Route (3GPP TS 24.229)
- store the list of service route values contained in the Service-Route header field and bind the list to the contact
- address used in registration, in order to build a proper preloaded Route header field value for new dialogs and
- standalone transactions when using the respective contact address.
- */
- for(index = 0; (hdr_Service_Route = (const tsip_header_Service_Route_t*)tsip_message_get_headerAt(response, tsip_htype_Service_Route, index)); index++){
- if(!TSIP_DIALOG_GET_STACK(self)->service_routes){
- TSIP_DIALOG_GET_STACK(self)->service_routes = tsk_list_create();
- }
- uri = tsk_object_ref(hdr_Service_Route->uri);
- tsk_list_push_back_data(TSIP_DIALOG_GET_STACK(self)->service_routes, (void**)&uri);
- }
-
- /* Paths */
- for(index = 0; (hdr_Path = (const tsip_header_Path_t*)tsip_message_get_headerAt(response, tsip_htype_Path, index)); index++){
- if(TSIP_DIALOG_GET_STACK(self)->paths == 0){
- TSIP_DIALOG_GET_STACK(self)->paths = tsk_list_create();
- }
- uri = tsk_object_ref(hdr_Path->uri);
- tsk_list_push_back_data(TSIP_DIALOG_GET_STACK(self)->paths, (void**)&uri);
- }
- }
-
- /* 3GPP TS 24.229 - 5.1.1.2 Initial registration */
- if(first_time_to_connect){
- tsk_bool_t barred = tsk_true;
- const tsk_list_item_t *item;
- const tsip_uri_t *uri;
- const tsip_uri_t *uri_first = 0;
-
- /*
- b) store as the default public user identity the first URI on the list of URIs present in the P-Associated-URI header
- field and bind it to the respective contact address of the UE and the associated set of security associations or TLS
- session;
- NOTE 4: When using the respective contact address and associated set of security associations or TLS session, the
- UE can utilize additional URIs contained in the P-Associated-URI header field and bound it to the
- respective contact address of the UE and the associated set of security associations or TLS session, e.g. for
- application purposes.
- c) treat the identity under registration as a barred public user identity, if it is not included in the P-Associated-URI
- header field;
- */
- tsk_list_foreach(item, TSIP_DIALOG_GET_STACK(self)->associated_uris){
- uri = item->data;
- if(item == TSIP_DIALOG_GET_STACK(self)->associated_uris->head){
- uri_first = item->data;
- }
- if(!tsk_object_cmp(TSIP_DIALOG_GET_STACK(self)->identity.preferred, uri)){
- barred = 0;
- break;
- }
- }
-
- if(barred && uri_first){
- TSK_OBJECT_SAFE_FREE(TSIP_DIALOG_GET_STACK(self)->identity.preferred);
- TSIP_DIALOG_GET_STACK(self)->identity.preferred = tsk_object_ref((void*)uri_first);
- }
- }
-
- /* Update the dialog state */
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), response))){
- return ret;
- }
-
- /* Reset current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), tsk_null);
-
- /* Request timeout for dialog refresh (re-registration). */
- self->timerrefresh.timeout = tsip_dialog_get_newdelay(TSIP_DIALOG(self), response);
- TSIP_DIALOG_REGISTER_TIMER_SCHEDULE(refresh);
-
- /* Alert the user (session) */
- TSIP_DIALOG_REGISTER_SIGNAL(self, tsip_ao_register,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- /* Alert the user (dialog) */
- if(first_time_to_connect){
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connected, "Dialog connected");
- }
-
- return ret;
-}
-
-/* InProgress -> (2xx) -> Terminated
-*/
-int tsip_dialog_register_InProgress_2_Terminated_X_2xx(va_list *app)
-{
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
-
- /* Alert the user */
- TSIP_DIALOG_REGISTER_SIGNAL(self, tsip_ao_unregister,
- TSIP_RESPONSE_CODE(message), TSIP_RESPONSE_PHRASE(message), message);
-
- return 0;
-}
-
-/* InProgress --> (401/407/421/494) --> InProgress
-*/
-int tsip_dialog_register_InProgress_2_InProgress_X_401_407_421_494(va_list *app)
-{
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
- int ret;
-
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), response))){
- /* Alert the user. */
- TSIP_DIALOG_REGISTER_SIGNAL(self, self->unregistering ? tsip_ao_unregister : tsip_ao_register,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), "Authentication failed");
-
- return ret;
- }
-
- /* Ensure IPSec SAs */
- if(TSIP_DIALOG_GET_STACK(self)->security.secagree_mech && tsk_striequals(TSIP_DIALOG_GET_STACK(self)->security.secagree_mech, "ipsec-3gpp")){
- tsip_transport_ensureTempSAs(TSIP_DIALOG_GET_STACK(self)->layer_transport, response, TSIP_DIALOG(self)->expires);
- }
-
- return tsip_dialog_register_send_REGISTER(self, tsk_false);
-}
-
-/* InProgress -> (423) -> InProgress
-*/
-int tsip_dialog_register_InProgress_2_InProgress_X_423(va_list *app)
-{
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
-
- tsip_header_Min_Expires_t *hdr;
- int ret = 0;
-
- /*
- RFC 3261 - 10.2.8 Error Responses
-
- If a UA receives a 423 (Interval Too Brief) response, it MAY retry
- the registration after making the expiration interval of all contact
- addresses in the REGISTER request equal to or greater than the
- expiration interval within the Min-Expires header field of the 423
- (Interval Too Brief) response.
- */
- hdr = (tsip_header_Min_Expires_t*)tsip_message_get_header(message, tsip_htype_Min_Expires);
- if(hdr){
- TSIP_DIALOG(self)->expires = TSK_TIME_S_2_MS(hdr->value);
-
- if(tsk_striequals(TSIP_DIALOG_GET_STACK(self)->security.secagree_mech, "ipsec-3gpp")){
- tsip_transport_cleanupSAs(TSIP_DIALOG_GET_STACK(self)->layer_transport);
- ret = tsip_dialog_register_send_REGISTER(self, tsk_true);
- }
- else{
- ret = tsip_dialog_register_send_REGISTER(self, tsk_false);
- }
- }
- else{
- ret = -1;
- }
-
- return ret;
-}
-
-/* InProgress -> (300-699) -> Terminated
-*/
-int tsip_dialog_register_InProgress_2_Terminated_X_300_to_699(va_list *app)
-{
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* set last error (or info) */
- tsip_dialog_set_lasterror(TSIP_DIALOG(self), TSIP_RESPONSE_PHRASE(response));
-
- /* Alert the user. */
- TSIP_DIALOG_REGISTER_SIGNAL(self, self->unregistering ? tsip_ao_unregister : tsip_ao_register,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return 0;
-}
-
-/* InProgress -> (cancel) -> Terminated
-*/
-int tsip_dialog_register_InProgress_2_Terminated_X_cancel(va_list *app)
-{
- int ret;
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- /* const tsip_message_t *message = va_arg(*app, const tsip_message_t *); */
-
- /* Cancel all transactions associated to this dialog (will also be done when the dialog is destroyed (worth nothing)) */
- ret = tsip_transac_layer_cancel_by_dialog(TSIP_DIALOG_GET_STACK(self)->layer_transac, TSIP_DIALOG(self));
-
- /* RFC 3261 - 9.1 Client Behavior
- A CANCEL request SHOULD NOT be sent to cancel a request other than INVITE.
- */
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_request_cancelled, "Registration cancelled");
-
- return ret;
-}
-
-/* Connected -> (REGISTER) -> InProgress
-*/
-int tsip_dialog_register_Connected_2_InProgress_X_oRegister(va_list *app)
-{
- tsip_dialog_register_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_register_t *);
- /*const tsip_message_t *message =*/ va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* Set current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- return tsip_dialog_register_send_REGISTER(self, tsk_true);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.server.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.server.c
deleted file mode 100644
index a7aa491..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_register.server.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as publishd by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-#include "tinysip/dialogs/tsip_dialog_register.h"
-#include "tinysip/dialogs/tsip_dialog_register.common.h"
-
-
-/* ======================== external functions ======================== */
-extern int tsip_dialog_register_send_RESPONSE(tsip_dialog_register_t *self, const tsip_request_t* request, short code, const char* phrase);
-
-/* ======================== transitions ======================== */
-int s0000_Started_2_Terminated_X_iREGISTER(va_list *app);
-int s0000_Started_2_Incoming_X_iREGISTER(va_list *app);
-int s0000_Incoming_2_Connected_X_Accept(va_list *app);
-int s0000_Incoming_2_Terminated_X_Reject(va_list *app);
-int s0000_Connected_2_Terminated_X_iREGISTER(va_list *app);
-
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_not_served_here(tsip_dialog_register_t* dialog, tsip_message_t* message)
-{
- if(message && TSIP_REQUEST_IS_REGISTER(message)){
- if(tsk_object_cmp(TSIP_DIALOG_GET_STACK(dialog)->network.realm, message->line.request.uri) != 0){
- tsip_dialog_register_send_RESPONSE(dialog, TSIP_MESSAGE_AS_REQUEST(message), 404, "Domain not served here");
- return tsk_true;
- }
- }
- return tsk_false;
-}
-static tsk_bool_t _fsm_cond_server_unregistering(tsip_dialog_register_t* dialog, tsip_message_t* message)
-{
- if(message && dialog->is_server){
- int64_t expires = tsip_message_getExpires(message);
- dialog->unregistering = (expires == 0);
- return dialog->unregistering;
- }
- return tsk_false;
-}
-static tsk_bool_t _fsm_cond_server_registering(tsip_dialog_register_t* dialog, tsip_message_t* message)
-{
- return !_fsm_cond_server_unregistering(dialog, message);
-}
-
-
-int tsip_dialog_register_server_init(tsip_dialog_register_t *self)
-{
- return tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Started ===
- */
- // Started -> (Domain Not Served here) -> Terminated
- TSK_FSM_ADD(_fsm_state_Started, _fsm_action_iREGISTER, _fsm_cond_not_served_here, _fsm_state_Terminated, s0000_Started_2_Terminated_X_iREGISTER, "s0000_Started_2_Terminated_X_iREGISTER"),
- // Started -> (All is OK and we are not unRegistering) -> Trying
- TSK_FSM_ADD(_fsm_state_Started, _fsm_action_iREGISTER, _fsm_cond_server_registering, _fsm_state_Incoming, s0000_Started_2_Incoming_X_iREGISTER, "s0000_Started_2_Incoming_X_iREGISTER"),
-
- /*=======================
- * === Incoming ===
- */
- // Incoming -> (Accept) -> Connected
- TSK_FSM_ADD_ALWAYS(_fsm_state_Incoming, _fsm_action_accept, _fsm_state_Connected, s0000_Incoming_2_Connected_X_Accept, "s0000_Incoming_2_Connected_X_Accept"),
- // Incoming -> (Reject) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Incoming, _fsm_action_reject, _fsm_state_Terminated, s0000_Incoming_2_Terminated_X_Reject, "s0000_Incoming_2_Terminated_X_Reject"),
-
- /*=======================
- * === Connected ===
- */
- // Connected -> (UnRegister) -> Terminated
- TSK_FSM_ADD(_fsm_state_Connected, _fsm_action_iREGISTER, _fsm_cond_server_unregistering, _fsm_state_Terminated, s0000_Connected_2_Terminated_X_iREGISTER, "s0000_Connected_2_Terminated_X_iREGISTER"),
- // Connected -> (TimedOut) -> Terminated
- // Connected -> (Refresh OK) -> Connected
- // Connected -> (Refresh NOK) -> Terminated
-
- TSK_FSM_ADD_NULL());
-}
-
-
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-/* Started -> (Failure) -> Terminated
-*/
-int s0000_Started_2_Terminated_X_iREGISTER(va_list *app)
-{
- return 0;
- /*tsip_dialog_register_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_register_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- TSIP_DIALOG(self)->running = tsk_true;
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- // alert the user
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connecting, "Dialog connecting");
-
- return send_REGISTER(self, tsk_true);*/
-}
-
-/* Started -> (All is OK and we are Registering) -> Incoming
-*/
-int s0000_Started_2_Incoming_X_iREGISTER(va_list *app)
-{
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- // set as server side dialog
- TSIP_DIALOG_REGISTER(self)->is_server = tsk_true;
-
- /* update last REGISTER */
- TSK_OBJECT_SAFE_FREE(self->last_iRegister);
- self->last_iRegister = tsk_object_ref(request);
-
- /* alert the user (session) */
- TSIP_DIALOG_REGISTER_SIGNAL(self, tsip_i_newreg,
- tsip_event_code_dialog_request_incoming, "Incoming New Register", request);
-
- return 0;
-}
-
-/* Incoming -> (Accept) -> Connected
-*/
-int s0000_Incoming_2_Connected_X_Accept(va_list *app)
-{
- int ret;
-
- tsip_dialog_register_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_register_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* update current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* send 2xx OK */
- if((ret = tsip_dialog_register_send_RESPONSE(self, self->last_iRegister, 200, "OK"))){
- return ret;
- }
-
- /* alert the user (dialog) */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connected, "Dialog connected");
-
- return ret;
-}
-
-/* Incoming -> (Reject) -> Terminated
-*/
-int s0000_Incoming_2_Terminated_X_Reject(va_list *app)
-{
- return -1;
-}
-
-/* Incoming -> (Unregister) -> Terminated
-*/
-int s0000_Connected_2_Terminated_X_iREGISTER(va_list *app)
-{
- int ret;
- tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
- tsip_request_t *request = va_arg(*app, tsip_request_t *);
-
- /* update last REGISTER */
- TSK_OBJECT_SAFE_FREE(self->last_iRegister);
- self->last_iRegister = tsk_object_ref(request);
-
- /* send 2xx OK */
- if((ret = tsip_dialog_register_send_RESPONSE(self, self->last_iRegister, 200, "OK"))){
- return ret;
- }
-
- /* alert the user (session) */
- TSIP_DIALOG_REGISTER_SIGNAL(self, tsip_i_unregister,
- tsip_event_code_dialog_request_incoming, "Incoming Request", request);
-
- return 0;
-} \ No newline at end of file
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_subscribe.client.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_subscribe.client.c
deleted file mode 100644
index 5479750..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_subscribe.client.c
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
-* Copyright (C) 2009-2010 Mamadou Diop.
-*
-* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
-*
-* This file is part of Open Source Doubango Framework.
-*
-* DOUBANGO is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* DOUBANGO is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with DOUBANGO.
-*
-*/
-
-/**@file tsip_dialog_subscribe.client.c
- * @brief SIP dialog SUBSCRIBE (Client side) as per RFC 3265.
- *
- * @author Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * @date Created: Sat Nov 8 16:54:58 2009 mdiop
- */
-#include "tinysip/dialogs/tsip_dialog_subscribe.h"
-
-#include "tinysip/headers/tsip_header_Dummy.h"
-#include "tinysip/headers/tsip_header_Event.h"
-#include "tinysip/headers/tsip_header_Min_Expires.h"
-#include "tinysip/headers/tsip_header_Subscription_State.h"
-
-#include "tinysip/transactions/tsip_transac_layer.h"
-
-#include "tinysip/api/tsip_api_subscribe.h"
-
-#include "tsk_debug.h"
-#include "tsk_time.h"
-
-
-
-#define DEBUG_STATE_MACHINE 0
-#define TSIP_DIALOG_SUBSCRIBE_TIMER_SCHEDULE(TX) TSIP_DIALOG_TIMER_SCHEDULE(subscribe, TX)
-#define TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, type, code, phrase, message) \
- tsip_subscribe_event_signal(type, TSIP_DIALOG(self)->ss, code, phrase, message)
-
-/* ======================== internal functions ======================== */
-int send_SUBSCRIBE(tsip_dialog_subscribe_t *self);
-int send_200NOTIFY(tsip_dialog_subscribe_t *self, const tsip_request_t* request);
-int tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self);
-
-/* ======================== transitions ======================== */
-int tsip_dialog_subscribe_Started_2_Trying_X_subscribe(va_list *app);
-int tsip_dialog_subscribe_Trying_2_Trying_X_1xx(va_list *app);
-int tsip_dialog_subscribe_Trying_2_Terminated_X_2xx(va_list *app);
-int tsip_dialog_subscribe_Trying_2_Connected_X_2xx(va_list *app);
-int tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494(va_list *app);
-int tsip_dialog_subscribe_Trying_2_Trying_X_423(va_list *app);
-int tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699(va_list *app);
-int tsip_dialog_subscribe_Trying_2_Terminated_X_cancel(va_list *app);
-int tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY(va_list *app);
-int tsip_dialog_subscribe_Connected_2_Trying_X_unsubscribe(va_list *app);
-int tsip_dialog_subscribe_Connected_2_Trying_X_subscribe(va_list *app);
-int tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY(va_list *app);
-int tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY(va_list *app);
-int tsip_dialog_subscribe_Any_2_Trying_X_hangup(va_list *app);
-int tsip_dialog_subscribe_Any_2_Trying_X_shutdown(va_list *app);
-int tsip_dialog_subscribe_Any_2_Terminated_X_transportError(va_list *app);
-int tsip_dialog_subscribe_Any_2_Terminated_X_Error(va_list *app);
-
-
-/* ======================== conds ======================== */
-static tsk_bool_t _fsm_cond_unsubscribing(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
-{
- return dialog->unsubscribing;
-}
-static tsk_bool_t _fsm_cond_subscribing(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
-{
- return !_fsm_cond_unsubscribing(dialog, message);
-}
-
-static tsk_bool_t _fsm_cond_notify_terminated(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
-{
- const tsip_header_Subscription_State_t *hdr_state;
- if((hdr_state = (const tsip_header_Subscription_State_t*)tsip_message_get_header(message, tsip_htype_Subscription_State)))
- {
- return tsk_striequals(hdr_state->state, "terminated") &&
- (hdr_state->expires < 0 || tsk_striequals(hdr_state->reason, "rejected") || tsk_striequals(hdr_state->reason, "noresource"));
- }
- return tsk_false;
-}
-static tsk_bool_t _fsm_cond_notify_not_terminated(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
-{
- return !_fsm_cond_notify_terminated(dialog, message);
-}
-
-static tsk_bool_t _fsm_cond_silent_hangup(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
-{
- return TSIP_DIALOG(dialog)->ss->silent_hangup;
-}
-static tsk_bool_t _fsm_cond_not_silent_hangup(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
-{
- return !TSIP_DIALOG(dialog)->ss->silent_hangup;
-}
-#define _fsm_cond_silent_shutdown _fsm_cond_silent_hangup
-#define _fsm_cond_not_silent_shutdown _fsm_cond_not_silent_hangup
-
-/* ======================== actions ======================== */
-typedef enum _fsm_action_e
-{
- _fsm_action_subscribe = tsip_atype_subscribe,
- _fsm_action_hangup = tsip_atype_hangup,
- _fsm_action_cancel = tsip_atype_cancel,
- _fsm_action_shutdown = tsip_atype_shutdown,
-
- _fsm_action_1xx = 0xFF,
- _fsm_action_2xx,
- _fsm_action_401_407_421_494,
- _fsm_action_423,
- _fsm_action_300_to_699,
- _fsm_action_shutdown_timedout, /* Any -> Terminated */
- _fsm_action_notify,
- _fsm_action_transporterror,
- _fsm_action_error,
-}
-_fsm_action_t;
-
-/* ======================== states ======================== */
-typedef enum _fsm_state_e
-{
- _fsm_state_Started,
- _fsm_state_Trying,
- _fsm_state_Connected,
- _fsm_state_Terminated
-}
-_fsm_state_t;
-
-/**
- * Callback function called to alert the dialog for new events from the transaction/transport layers.
- *
- * @param [in,out] self A reference to the dialog.
- * @param type The event type.
- * @param [in,out] msg The incoming SIP/IMS message.
- *
- * @return Zero if succeed and non-zero error code otherwise.
-**/
-int tsip_dialog_subscribe_event_callback(const tsip_dialog_subscribe_t *self, tsip_dialog_event_type_t type, const tsip_message_t *msg)
-{
- int ret = -1;
-
- switch(type)
- {
- case tsip_dialog_i_msg:
- {
- if(msg && TSIP_MESSAGE_IS_RESPONSE(msg))
- {
- //
- // RESPONSE
- //
- if(TSIP_RESPONSE_IS_1XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_1xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS_2XX(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_2xx, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS(msg,401) || TSIP_RESPONSE_IS(msg,407) || TSIP_RESPONSE_IS(msg,421) || TSIP_RESPONSE_IS(msg,494)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_401_407_421_494, msg, tsk_null);
- }
- else if(TSIP_RESPONSE_IS(msg,423)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_423, msg, tsk_null);
- }
- else{
- // Alert User
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_error, msg, tsk_null);
- /* TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); */
- }
- }
- else
- {
- //
- // REQUEST
- //
- if(TSIP_REQUEST_IS_NOTIFY(msg)){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_notify, msg, tsk_null);
- }
- }
- break;
- }
-
- case tsip_dialog_canceled:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_cancel, msg, tsk_null);
- break;
- }
-
- case tsip_dialog_terminated:
- case tsip_dialog_timedout:
- case tsip_dialog_error:
- case tsip_dialog_transport_error:
- {
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_transporterror, msg, tsk_null);
- break;
- }
- }
-
- return ret;
-}
-
-/** Timer manager callback.
- *
- * @param [in,out] self The owner of the signaled timer.
- * @param timer_id The identifier of the signaled timer.
- *
- * @return Zero if succeed and non-zero error code otherwise.
-**/
-int tsip_dialog_subscribe_timer_callback(const tsip_dialog_subscribe_t* self, tsk_timer_id_t timer_id)
-{
- int ret = -1;
-
- if(self)
- {
- if(timer_id == self->timerrefresh.id){
- tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_subscribe, tsk_null, tsk_null);
- ret = 0;
- }
- else if(timer_id == self->timershutdown.id){
- ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_shutdown_timedout, tsk_null, tsk_null);
- }
- }
- return ret;
-}
-
-tsip_dialog_subscribe_t* tsip_dialog_subscribe_create(const tsip_ssession_handle_t* ss)
-{
- return tsk_object_new(tsip_dialog_subscribe_def_t, ss);
-}
-
-/** Initializes the dialog.
- *
- * @param [in,out] self The dialog to initialize.
-**/
-int tsip_dialog_subscribe_init(tsip_dialog_subscribe_t *self)
-{
- /* Initialize the State Machine. */
- tsk_fsm_set(TSIP_DIALOG_GET_FSM(self),
-
- /*=======================
- * === Started ===
- */
- // Started -> (Send) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_subscribe, _fsm_state_Trying, tsip_dialog_subscribe_Started_2_Trying_X_subscribe, "tsip_dialog_subscribe_Started_2_Trying_X_subscribe"),
- // Started -> (Any) -> Started
- TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_dialog_subscribe_Started_2_Started_X_any"),
-
-
- /*=======================
- * === Trying ===
- */
- // Trying -> (1xx) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_1xx, _fsm_state_Trying, tsip_dialog_subscribe_Trying_2_Trying_X_1xx, "tsip_dialog_subscribe_Trying_2_Trying_X_1xx"),
- // Trying -> (2xx) -> Terminated
- TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_2xx, _fsm_cond_unsubscribing, _fsm_state_Terminated, tsip_dialog_subscribe_Trying_2_Terminated_X_2xx, "tsip_dialog_subscribe_Trying_2_Terminated_X_2xx"),
- // Trying -> (2xx) -> Connected
- TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_2xx, _fsm_cond_subscribing, _fsm_state_Connected, tsip_dialog_subscribe_Trying_2_Connected_X_2xx, "tsip_dialog_subscribe_Trying_2_Connected_X_2xx"),
- // Trying -> (401/407/421/494) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_401_407_421_494, _fsm_state_Trying, tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494, "tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494"),
- // Trying -> (423) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_423, _fsm_state_Trying, tsip_dialog_subscribe_Trying_2_Trying_X_423, "tsip_dialog_subscribe_Trying_2_Trying_X_423"),
- // Trying -> (300_to_699) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_300_to_699, _fsm_state_Terminated, tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699, "tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699"),
- // Trying -> (cancel) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_cancel, _fsm_state_Terminated, tsip_dialog_subscribe_Trying_2_Terminated_X_cancel, "tsip_dialog_subscribe_Trying_2_Terminated_X_cancel"),
- // Trying -> (Notify) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_notify, _fsm_state_Trying, tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY, "tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY"),
- // Trying -> (hangup) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_hangup, _fsm_state_Terminated, tsk_null, "tsip_dialog_subscribe_Trying_2_Terminated_X_hangup"),
- // Trying -> (shutdown) -> Terminated
- TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_shutdown, _fsm_state_Terminated, tsk_null, "tsip_dialog_subscribe_Trying_2_Terminated_X_shutdown"),
- // Trying -> (Any) -> Trying
- //TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Trying, "tsip_dialog_subscribe_Trying_2_Trying_X_any"),
-
-
- /*=======================
- * === Connected ===
- */
- // Connected -> (SUBSCRIBE) -> Trying
- TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_subscribe, _fsm_state_Trying, tsip_dialog_subscribe_Connected_2_Trying_X_subscribe, "tsip_dialog_subscribe_Connected_2_Trying_X_subscribe"),
- // Connected -> (NOTIFY) -> Connected
- TSK_FSM_ADD(_fsm_state_Connected, _fsm_action_notify, _fsm_cond_notify_not_terminated, _fsm_state_Connected, tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY, "tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY"),
- // Connected -> (NOTIFY) -> Terminated
- TSK_FSM_ADD(_fsm_state_Connected, _fsm_action_notify, _fsm_cond_notify_terminated, _fsm_state_Terminated, tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY, "tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY"),
-
- /*=======================
- * === Any ===
- */
- // Any -> (hangup) -> Trying
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_hangup, _fsm_cond_not_silent_hangup, _fsm_state_Trying, tsip_dialog_subscribe_Any_2_Trying_X_hangup, "tsip_dialog_subscribe_Any_2_Trying_X_hangup"),
- // Any -> (silenthangup) -> Terminated
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_hangup, _fsm_cond_silent_hangup, _fsm_state_Terminated, tsk_null, "tsip_dialog_subscribe_Any_2_Trying_X_silenthangup"),
- // Any -> (shutdown) -> Trying
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_shutdown, _fsm_cond_not_silent_shutdown, _fsm_state_Trying, tsip_dialog_subscribe_Any_2_Trying_X_shutdown, "tsip_dialog_subscribe_Any_2_Trying_X_shutdown"),
- // Any -> (silentshutdown) -> Terminated
- TSK_FSM_ADD(tsk_fsm_state_any, _fsm_action_shutdown, _fsm_cond_silent_shutdown, _fsm_state_Terminated, tsk_null, "tsip_dialog_subscribe_Any_2_Trying_X_silentshutdown"),
- // Any -> (shutdown timedout) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_shutdown_timedout, _fsm_state_Terminated, tsk_null, "tsip_dialog_subscribe_shutdown_timedout"),
- // Any -> (transport error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_dialog_subscribe_Any_2_Terminated_X_transportError, "tsip_dialog_subscribe_Any_2_Terminated_X_transportError"),
- // Any -> (error) -> Terminated
- TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_dialog_subscribe_Any_2_Terminated_X_Error, "tsip_dialog_subscribe_Any_2_Terminated_X_Error"),
-
- TSK_FSM_ADD_NULL());
-
- /* Sets callback function */
- TSIP_DIALOG(self)->callback = TSIP_DIALOG_EVENT_CALLBACK_F(tsip_dialog_subscribe_event_callback);
-
- /* Timers */
- self->timerrefresh.id = TSK_INVALID_TIMER_ID;
- self->timerrefresh.timeout = TSIP_DIALOG(self)->expires;
- self->timershutdown.id = TSK_INVALID_TIMER_ID;
- self->timershutdown.timeout = TSIP_DIALOG_SHUTDOWN_TIMEOUT;
-
- return 0;
-}
-
-
-//--------------------------------------------------------
-// == STATE MACHINE BEGIN ==
-//--------------------------------------------------------
-
-/* Started -> (SUBSCRIBE) -> Trying
-*/
-int tsip_dialog_subscribe_Started_2_Trying_X_subscribe(va_list *app)
-{
- tsip_dialog_subscribe_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_subscribe_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- TSIP_DIALOG(self)->running = tsk_true;
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connecting, "Dialog connecting");
-
- return send_SUBSCRIBE(self);
-}
-
-/* Trying -> (1xx) -> Trying
-*/
-int tsip_dialog_subscribe_Trying_2_Trying_X_1xx(va_list *app)
-{
- /*tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);*/
- /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/
-
- return 0;
-}
-
-/* Trying -> (2xx) -> Terminated
-*/
-int tsip_dialog_subscribe_Trying_2_Terminated_X_2xx(va_list *app)
-{
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* Alert the user. */
- TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, self->unsubscribing ? tsip_ao_unsubscribe : tsip_ao_subscribe,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return 0;
-}
-
-/* Trying -> (2xx) -> Connected
-*/
-int tsip_dialog_subscribe_Trying_2_Connected_X_2xx(va_list *app)
-{
- int ret;
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- tsk_bool_t first_time_to_connect = (TSIP_DIALOG(self)->state == tsip_initial);
-
- /* Update the dialog state. */
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), response))){
- return ret;
- }
-
- /* Alert the user(session) */
- TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, self->unsubscribing ? tsip_ao_unsubscribe : tsip_ao_subscribe,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- /* Alert the user(dialog) */
- if(first_time_to_connect){
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connected, "Dialog connected");
- }
-
- /* Reset current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), tsk_null);
-
- /* Request timeout for dialog refresh (re-subscribtion). */
- self->timerrefresh.timeout = tsip_dialog_get_newdelay(TSIP_DIALOG(self), response);
- TSIP_DIALOG_SUBSCRIBE_TIMER_SCHEDULE(refresh);
-
- return 0;
-}
-
-/* Trying -> (401/407/421/494) -> Trying
-*/
-int tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494(va_list *app)
-{
- int ret;
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- if((ret = tsip_dialog_update(TSIP_DIALOG(self), response))){
- /* Alert the user. */
- TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, self->unsubscribing ? tsip_ao_unsubscribe : tsip_ao_subscribe,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return ret;
- }
-
- return send_SUBSCRIBE(self);
-}
-
-/* Trying -> (423) -> Trying
-*/
-int tsip_dialog_subscribe_Trying_2_Trying_X_423(va_list *app)
-{
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- tsip_header_Min_Expires_t *hdr;
-
- /*
- RFC 3261 - 10.2.8 Error Responses
-
- If a UA receives a 423 (Interval Too Brief) response, it MAY retry
- the registration after making the expiration interval of all contact
- addresses in the SUBSCRIBE request equal to or greater than the
- expiration interval within the Min-Expires header field of the 423
- (Interval Too Brief) response.
- */
- hdr = (tsip_header_Min_Expires_t*)tsip_message_get_header(response, tsip_htype_Min_Expires);
- if(hdr){
- TSIP_DIALOG(self)->expires = TSK_TIME_S_2_MS(hdr->value);
- send_SUBSCRIBE(self);
- }
- else{
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_message_error, "Received invalid SIP response.");
-
- return -1;
- }
-
- return 0;
-}
-
-/* Trying -> (300-699) -> Terminated
-*/
-int tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699(va_list *app)
-{
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* Alert the user. */
- TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, self->unsubscribing ? tsip_ao_unsubscribe : tsip_ao_subscribe,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
-
- return 0;
-}
-
-/* Trying -> (cancel) -> Terminated
-*/
-int tsip_dialog_subscribe_Trying_2_Terminated_X_cancel(va_list *app)
-{
- int ret;
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- /* const tsip_response_t *response = va_arg(*app, const tsip_response_t *); */
-
- /* Cancel all transactions associated to this dialog (will also be done when the dialog is destroyed (worth nothing)) */
- ret = tsip_transac_layer_cancel_by_dialog(TSIP_DIALOG_GET_STACK(self)->layer_transac, TSIP_DIALOG(self));
-
- /* RFC 3261 - 9.1 Client Behavior
- A CANCEL request SHOULD NOT be sent to cancel a request other than INVITE.
- */
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_request_cancelled, "Subscription cancelled");
-
- return ret;
-}
-
-/* Trying -> (NOTIFY) -> Trying
-*/
-int tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY(va_list *app)
-{
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- const tsip_request_t *request = va_arg(*app, const tsip_request_t *);
-
- return send_200NOTIFY(self, request);
-}
-
-/* Connected -> (SUBSCRIBE) -> Trying
-*/
-int tsip_dialog_subscribe_Connected_2_Trying_X_subscribe(va_list *app)
-{
- tsip_dialog_subscribe_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_subscribe_t *);
- va_arg(*app, const tsip_message_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* Set current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- return send_SUBSCRIBE(self);
-}
-
-/* Connected -> (NOTIFY) -> Connected
-*/
-int tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY(va_list *app)
-{
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- const tsip_request_t *request = va_arg(*app, const tsip_request_t *);
- int ret;
-
- ret = send_200NOTIFY(self, request);
-
- /* Request timeout for dialog refresh (re-registration). */
- self->timerrefresh.timeout = tsip_dialog_get_newdelay(TSIP_DIALOG(self), request);
- TSIP_DIALOG_SUBSCRIBE_TIMER_SCHEDULE(refresh);
-
- /* Alert the user */
- TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, tsip_i_notify,
- tsip_event_code_dialog_request_incoming, "Incoming NOTIFY.", request);
-
- return ret;
-}
-
-/* Connected -> (NOTIFY) -> Terminated
-*/
-int tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY(va_list *app)
-{
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- const tsip_request_t *request = va_arg(*app, const tsip_request_t *);
-
- /* Alert the user */
- TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, tsip_i_notify,
- tsip_event_code_dialog_request_incoming, "Incoming NOTIFY.", request);
-
- return send_200NOTIFY(self, request);
-}
-
-/* Any -> (hangup) -> Trying
-*/
-int tsip_dialog_subscribe_Any_2_Trying_X_hangup(va_list *app)
-{
- tsip_dialog_subscribe_t *self;
- const tsip_action_t* action;
-
- self = va_arg(*app, tsip_dialog_subscribe_t *);
- /*const tsip_response_t *response =*/ va_arg(*app, const tsip_response_t *);
- action = va_arg(*app, const tsip_action_t *);
-
- /* Set current action */
- tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminating, "Terminating dialog");
-
- self->unsubscribing = tsk_true;
- return send_SUBSCRIBE(self);
-}
-
-/* Any -> (shutdown) -> Trying
-*/
-int tsip_dialog_subscribe_Any_2_Trying_X_shutdown(va_list *app)
-{
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
-
- /* schedule shutdow timeout */
- TSIP_DIALOG_SUBSCRIBE_TIMER_SCHEDULE(shutdown);
-
- /* alert user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminating, "Terminating dialog");
-
- self->unsubscribing = tsk_true;
- return send_SUBSCRIBE(self);
-}
-
-/* Any -> (transport error) -> Terminated
-*/
-int tsip_dialog_subscribe_Any_2_Terminated_X_transportError(va_list *app)
-{
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- /* const tsip_response_t *response = va_arg(*app, const tsip_response_t *); */
-
- /* Alert the user. */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_transport_error, "Transport error.");
-
- return 0;
-}
-
-/* Any -> (error) -> Terminated
-*/
-int tsip_dialog_subscribe_Any_2_Terminated_X_Error(va_list *app)
-{
- tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
- const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
-
- /* Alert user */
- if(response){
- TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, self->unsubscribing ? tsip_ao_unsubscribe : tsip_ao_subscribe,
- TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);
- }
- else{
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_global_error, "Global error.");
- }
-
- return 0;
-}
-
-
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-// == STATE MACHINE END ==
-//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-/**
- * Sends a SUBSCRIBE request.
- *
- * @param [in,out] self The caller.
- *
- * @return Zero if succeed and non-zero error code otherwise.
-**/
-int send_SUBSCRIBE(tsip_dialog_subscribe_t *self)
-{
- tsip_request_t *request;
- int ret = -1;
-
- if(self->unsubscribing){
- TSIP_DIALOG(self)->expires = 0;
- }
-
- if((request = tsip_dialog_request_new(TSIP_DIALOG(self), "SUBSCRIBE"))){
- /* apply action params to the request */
- if(TSIP_DIALOG(self)->curr_action){
- tsip_dialog_apply_action(request, TSIP_DIALOG(self)->curr_action);
- }
- /* send the request */
- ret = tsip_dialog_request_send(TSIP_DIALOG(self), request);
- TSK_OBJECT_SAFE_FREE(request);
- }
-
- return ret;
-}
-
-int send_200NOTIFY(tsip_dialog_subscribe_t *self, const tsip_request_t* request)
-{
- tsip_response_t *response;
- int ret = -1;
-
- if((response = tsip_dialog_response_new(TSIP_DIALOG(self), 200, "OK", request))){
- ret = tsip_dialog_response_send(TSIP_DIALOG(self), response);
- TSK_OBJECT_SAFE_FREE(response);
- }
- return ret;
-}
-
-/**
- * Callback function called by the state machine manager to signal that the final state has been reached.
- *
- * @param [in,out] self The state machine owner.
-**/
-int tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self)
-{
- TSK_DEBUG_INFO("=== SUBSCRIBE Dialog terminated ===");
-
- /* Alert the user */
- TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_terminated,
- TSIP_DIALOG(self)->lasterror ? TSIP_DIALOG(self)->lasterror : "Dialog terminated");
-
- /* Remove from the dialog layer. */
- return tsip_dialog_remove(TSIP_DIALOG(self));
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-//========================================================
-// SIP dialog SUBSCRIBE object definition
-//
-static tsk_object_t* tsip_dialog_subscribe_ctor(tsk_object_t * self, va_list * app)
-{
- tsip_dialog_subscribe_t *dialog = self;
- if(dialog){
- tsip_ssession_handle_t *ss = va_arg(*app, tsip_ssession_handle_t *);
-
- /* Initialize base class */
- tsip_dialog_init(TSIP_DIALOG(self), tsip_dialog_SUBSCRIBE, tsk_null, ss, _fsm_state_Started, _fsm_state_Terminated);
-
- /* FSM */
- TSIP_DIALOG_GET_FSM(self)->debug = DEBUG_STATE_MACHINE;
- tsk_fsm_set_callback_terminated(TSIP_DIALOG_GET_FSM(self), TSK_FSM_ONTERMINATED_F(tsip_dialog_subscribe_OnTerminated), (const void*)dialog);
-
- /* Initialize the class itself */
- tsip_dialog_subscribe_init(self);
- }
- return self;
-}
-
-static tsk_object_t* tsip_dialog_subscribe_dtor(tsk_object_t * _self)
-{
- tsip_dialog_subscribe_t *self = _self;
- if(self){
- /* Cancel all timers */
- TSIP_DIALOG_TIMER_CANCEL(refresh);
- TSIP_DIALOG_TIMER_CANCEL(shutdown);
-
- /* DeInitialize base class (will cancel all transactions) */
- tsip_dialog_deinit(TSIP_DIALOG(self));
-
- TSK_DEBUG_INFO("*** SUBSCRIBE Dialog destroyed ***");
- }
- return self;
-}
-
-static int tsip_dialog_subscribe_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
-{
- return tsip_dialog_cmp(obj1, obj2);
-}
-
-static const tsk_object_def_t tsip_dialog_subscribe_def_s =
-{
- sizeof(tsip_dialog_subscribe_t),
- tsip_dialog_subscribe_ctor,
- tsip_dialog_subscribe_dtor,
- tsip_dialog_subscribe_cmp,
-};
-const tsk_object_def_t *tsip_dialog_subscribe_def_t = &tsip_dialog_subscribe_def_s;
diff --git a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_subscribe.server.c b/branches/1.0/tinySIP/src/dialogs/tsip_dialog_subscribe.server.c
deleted file mode 100644
index d3f5a12..0000000
--- a/branches/1.0/tinySIP/src/dialogs/tsip_dialog_subscribe.server.c
+++ /dev/null
@@ -1 +0,0 @@
-
OpenPOWER on IntegriCloud