ict.c 8.41 KB
Newer Older
1 2 3 4 5 6
/*
	belle-sip - SIP (RFC3261) library.
    Copyright (C) 2010  Belledonne Communications SARL

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 2 of the License, or
8 9 10 11 12 13 14 15 16 17 18
    (at your option) any later version.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

19
/**
20 21
 * INVITE client transaction implementation.
**/
22

23 24
#include <bctoolbox/defs.h>

25 26 27
#include "belle_sip_internal.h"


28
static void on_ict_terminate(belle_sip_ict_t *obj){
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
	if (obj->timer_A){
		belle_sip_transaction_stop_timer(base,obj->timer_A);
		belle_sip_object_unref(obj->timer_A);
		obj->timer_A=NULL;
	}
	if (obj->timer_B){
		belle_sip_transaction_stop_timer(base,obj->timer_B);
		belle_sip_object_unref(obj->timer_B);
		obj->timer_B=NULL;
	}
	if (obj->timer_D){
		belle_sip_transaction_stop_timer(base,obj->timer_D);
		belle_sip_object_unref(obj->timer_D);
		obj->timer_D=NULL;
	}
45 46 47 48 49
	if (obj->timer_M){
		belle_sip_transaction_stop_timer(base,obj->timer_M);
		belle_sip_object_unref(obj->timer_M);
		obj->timer_M=NULL;
	}
50 51 52 53 54 55
	if (obj->ack){
		belle_sip_object_unref(obj->ack);
		obj->ack=NULL;
	}
}

56 57 58 59
static void ict_destroy(belle_sip_ict_t *obj){
	on_ict_terminate(obj);
}

60 61 62 63
static belle_sip_request_t *make_ack(belle_sip_ict_t *obj, belle_sip_response_t *resp){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
	if (obj->ack==NULL){
		obj->ack=belle_sip_request_new();
64
		belle_sip_object_ref(obj->ack);
65 66
		belle_sip_request_set_method(obj->ack,"ACK");
		belle_sip_request_set_uri(obj->ack,belle_sip_request_get_uri(base->request));
jehan's avatar
jehan committed
67 68 69 70 71 72
		belle_sip_util_copy_headers((belle_sip_message_t*)base->request,(belle_sip_message_t*)obj->ack,BELLE_SIP_VIA,FALSE);
		belle_sip_util_copy_headers((belle_sip_message_t*)base->request,(belle_sip_message_t*)obj->ack,BELLE_SIP_CALL_ID,FALSE);
		belle_sip_util_copy_headers((belle_sip_message_t*)base->request,(belle_sip_message_t*)obj->ack,BELLE_SIP_FROM,FALSE);
		belle_sip_util_copy_headers((belle_sip_message_t*)resp,(belle_sip_message_t*)obj->ack,BELLE_SIP_TO,FALSE);
		belle_sip_util_copy_headers((belle_sip_message_t*)base->request,(belle_sip_message_t*)obj->ack,BELLE_SIP_CONTACT,TRUE);
		belle_sip_util_copy_headers((belle_sip_message_t*)base->request,(belle_sip_message_t*)obj->ack,BELLE_SIP_ROUTE,TRUE);
73
		belle_sip_util_copy_headers((belle_sip_message_t*)base->request,(belle_sip_message_t*)obj->ack,BELLE_SIP_MAX_FORWARDS,FALSE);
74 75
		belle_sip_message_add_header((belle_sip_message_t*)obj->ack,
		(belle_sip_header_t*)belle_sip_header_cseq_create(
jehan's avatar
jehan committed
76
			belle_sip_header_cseq_get_seq_number((belle_sip_header_cseq_t*)belle_sip_message_get_header((belle_sip_message_t*)base->request,BELLE_SIP_CSEQ)),
Simon Morlat's avatar
Simon Morlat committed
77
		    "ACK"));
78
	}
jehan's avatar
jehan committed
79

80 81 82
	return obj->ack;
}

83
/* Timer D: Wait time for response retransmits */
84 85 86 87 88 89 90 91
static int ict_on_timer_D(belle_sip_ict_t *obj){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
	if (base->state==BELLE_SIP_TRANSACTION_COMPLETED){
		belle_sip_transaction_terminate(base);
	}
	return BELLE_SIP_STOP;
}

92
/* Timer M: Wait time for retransmission of 2xx to INVITE or additional 2xx from other branches of a forked INVITE */
93 94 95 96 97 98 99 100
static int ict_on_timer_M(belle_sip_ict_t *obj){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
	if (base->state==BELLE_SIP_TRANSACTION_ACCEPTED){
		belle_sip_transaction_terminate(base);
	}
	return BELLE_SIP_STOP;
}

101 102 103
static void ict_on_response(belle_sip_ict_t *obj, belle_sip_response_t *resp){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
	int code=belle_sip_response_get_status_code(resp);
104
	const belle_sip_timer_config_t *cfg=belle_sip_transaction_get_timer_config(base);
105 106 107

	switch (base->state){
		case BELLE_SIP_TRANSACTION_CALLING:
108
			belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_PROCEEDING);
109
			BCTBX_NO_BREAK; /*intentionally no break*/
110 111
		case BELLE_SIP_TRANSACTION_PROCEEDING:
			if (code>=300){
112
				belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_COMPLETED);
113
				belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)make_ack(obj,resp));
jehan's avatar
jehan committed
114
				belle_sip_client_transaction_notify_response((belle_sip_client_transaction_t*)obj,resp);
115
				obj->timer_D=belle_sip_timeout_source_new((belle_sip_source_func_t)ict_on_timer_D,obj,cfg->T1*64);
116 117
				belle_sip_transaction_start_timer(base,obj->timer_D);
			}else if (code>=200){
118 119
				obj->timer_M=belle_sip_timeout_source_new((belle_sip_source_func_t)ict_on_timer_M,obj,cfg->T1*64);
				belle_sip_transaction_start_timer(base,obj->timer_M);
120
				belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_ACCEPTED);
121
				belle_sip_client_transaction_notify_response((belle_sip_client_transaction_t*)obj,resp);
Simon Morlat's avatar
Simon Morlat committed
122 123
			}else if (code>=100){
				belle_sip_client_transaction_notify_response((belle_sip_client_transaction_t*)obj,resp);
124 125
			}
		break;
126 127 128 129 130
		case BELLE_SIP_TRANSACTION_ACCEPTED:
			if (code>=200 && code<300){
				belle_sip_client_transaction_notify_response((belle_sip_client_transaction_t*)obj,resp);
			}
		break;
131 132 133 134 135 136 137 138 139 140
		case BELLE_SIP_TRANSACTION_COMPLETED:
			if (code>=300 && obj->ack){
				belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)obj->ack);
			}
		break;
		default:
		break;
	}
}

141
/* Timer A: INVITE request retransmit interval, for UDP only */
142 143 144
static int ict_on_timer_A(belle_sip_ict_t *obj){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;

145
	if (!base->channel) return BELLE_SIP_STOP;
146

147 148 149 150 151 152 153 154 155 156 157 158
	switch(base->state){
		case BELLE_SIP_TRANSACTION_CALLING:
		{
			/*reset the timer to twice the previous value, and retransmit */
			unsigned int prev_timeout=belle_sip_source_get_timeout(obj->timer_A);
			belle_sip_source_set_timeout(obj->timer_A,2*prev_timeout);
			belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)base->request);
		}
		break;
		default:
		break;
	}
159

160
	return BELLE_SIP_CONTINUE;
161 162
}

163
/* Timer B: INVITE transaction timeout timer */
164 165 166 167 168 169 170 171 172 173
static int ict_on_timer_B(belle_sip_ict_t *obj){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
	switch (base->state){
		case BELLE_SIP_TRANSACTION_CALLING:
			belle_sip_transaction_notify_timeout(base);
		break;
		default:
		break;
	}
	return BELLE_SIP_STOP;
174 175
}

176 177 178 179 180 181 182 183 184
static void ict_stop_retransmissions(belle_sip_ict_t *obj){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
	belle_sip_message("ICT retransmissions stopped");
	if (obj->timer_A){
		belle_sip_transaction_stop_timer(base,obj->timer_A);
		belle_sip_object_unref(obj->timer_A);
		obj->timer_A=NULL;
	}
}
185

186 187
static void ict_send_request(belle_sip_ict_t *obj){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
188 189
	const belle_sip_timer_config_t *cfg=belle_sip_transaction_get_timer_config(base);

190
	belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_CALLING);
191

192 193 194 195 196 197 198
	if (!belle_sip_channel_is_reliable(base->channel)){
		obj->timer_A=belle_sip_timeout_source_new((belle_sip_source_func_t)ict_on_timer_A,obj,cfg->T1);
		belle_sip_transaction_start_timer(base,obj->timer_A);
	}

	obj->timer_B=belle_sip_timeout_source_new((belle_sip_source_func_t)ict_on_timer_B,obj,cfg->T1*64);
	belle_sip_transaction_start_timer(base,obj->timer_B);
199

Simon Morlat's avatar
Simon Morlat committed
200
	belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)base->request);
201 202 203 204
}

BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_ict_t);

205
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_ict_t)
206 207
	{
		{
208
			{
209
				BELLE_SIP_VPTR_INIT(belle_sip_ict_t,belle_sip_client_transaction_t,TRUE),
210 211
				(belle_sip_object_destroy_t)ict_destroy,
				NULL,
212
				NULL,
213 214
				(belle_sip_object_on_first_ref_t) NULL,
				(belle_sip_object_on_last_ref_t) NULL,
215
				BELLE_SIP_DEFAULT_BUFSIZE_HINT
216 217
			},
			(void (*)(belle_sip_transaction_t*))on_ict_terminate
218 219
		},
		(void (*)(belle_sip_client_transaction_t*))ict_send_request,
220 221
		(void (*)(belle_sip_client_transaction_t*,belle_sip_response_t*))ict_on_response,
		(void (*)(belle_sip_client_transaction_t*))ict_stop_retransmissions
222
	}
223
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
224 225 226 227 228 229 230


belle_sip_ict_t *belle_sip_ict_new(belle_sip_provider_t *prov, belle_sip_request_t *req){
	belle_sip_ict_t *obj=belle_sip_object_new(belle_sip_ict_t);
	belle_sip_client_transaction_init((belle_sip_client_transaction_t*)obj,prov,req);
	return obj;
}