channel.c 59.8 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 19 20
    (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/>.
*/


#include "belle_sip_internal.h"
21
#include <limits.h>
22
#include <ctype.h>
23
#include <wchar.h>
24

25
#ifdef __ANDROID__
26 27 28
#include "wakelock_internal.h"
#endif

29 30 31 32 33 34 35
#define BELLE_SIP_CHANNEL_INVOKE_MESSAGE_HEADERS_LISTENERS(channel,msg) \
	BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(channel->full_listeners, belle_sip_channel_listener_t, on_message_headers, channel, msg)

#define BELLE_SIP_CHANNEL_INVOKE_SENDING_LISTENERS(channel,msg) \
	BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(channel->full_listeners, belle_sip_channel_listener_t, on_sending, channel, msg)

#define BELLE_SIP_CHANNEL_INVOKE_STATE_LISTENERS(channel,state) \
36 37
	BELLE_SIP_INVOKE_LISTENERS_REVERSE_ARG1_ARG2(channel->full_listeners, belle_sip_channel_listener_t, on_state_changed, channel, state) \
	BELLE_SIP_INVOKE_LISTENERS_REVERSE_ARG1_ARG2(channel->state_listeners, belle_sip_channel_listener_t, on_state_changed, channel, state) 
38 39


40 41
static void channel_prepare_continue(belle_sip_channel_t *obj);
static void channel_process_queue(belle_sip_channel_t *obj);
42 43 44 45
static void channel_begin_send_background_task(belle_sip_channel_t *obj);
static void channel_end_send_background_task(belle_sip_channel_t *obj);
static void channel_begin_recv_background_task(belle_sip_channel_t *obj);
static void channel_end_recv_background_task(belle_sip_channel_t *obj);
46
static void channel_process_queue(belle_sip_channel_t *obj);
47
static char *make_logbuf(belle_sip_channel_t *obj, belle_sip_log_level level, const char *buffer, size_t size);
48
static void channel_remove_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l);
49
static void free_ewouldblock_buffer(belle_sip_channel_t *obj);
50

51
const char *belle_sip_channel_state_to_string(belle_sip_channel_state_t state){
52 53 54 55 56 57 58 59 60
	switch(state){
		case BELLE_SIP_CHANNEL_INIT:
			return "INIT";
		case BELLE_SIP_CHANNEL_RES_IN_PROGRESS:
			return "RES_IN_PROGRESS";
		case BELLE_SIP_CHANNEL_RES_DONE:
			return "RES_DONE";
		case BELLE_SIP_CHANNEL_CONNECTING:
			return "CONNECTING";
61 62
		case BELLE_SIP_CHANNEL_RETRY:
			return "RETRY";
63 64 65 66
		case BELLE_SIP_CHANNEL_READY:
			return "READY";
		case BELLE_SIP_CHANNEL_ERROR:
			return "ERROR";
jehan's avatar
jehan committed
67
		case BELLE_SIP_CHANNEL_DISCONNECTED:
68
			return "DISCONNECTED";
69 70
	}
	return "BAD";
71
}
72

73 74 75 76 77 78 79 80 81 82
static belle_sip_list_t * for_each_weak_unref_free(belle_sip_list_t *l, belle_sip_object_destroy_notify_t notify, void *ptr){
	belle_sip_list_t *elem,*next;
	for(elem=l;elem!=NULL;elem=next){
		next=elem->next;
		belle_sip_object_weak_unref(elem->data,notify,ptr);
		belle_sip_free(elem);
	}
	return NULL;
}

83 84 85
static void belle_sip_channel_input_stream_rewind(belle_sip_channel_input_stream_t* input_stream){
	int remaining;

86
	remaining=(int)(input_stream->write_ptr-input_stream->read_ptr);
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
	if (remaining>0){
		/* copy remaning bytes at top of buffer*/
		memmove(input_stream->buff,input_stream->read_ptr,remaining);
		input_stream->read_ptr=input_stream->buff;
		input_stream->write_ptr=input_stream->buff+remaining;
		*input_stream->write_ptr='\0';
	}else{
		input_stream->read_ptr=input_stream->write_ptr=input_stream->buff;
	}
}

static void belle_sip_channel_input_stream_reset(belle_sip_channel_input_stream_t* input_stream) {
	belle_sip_channel_input_stream_rewind(input_stream);
	input_stream->state=WAITING_MESSAGE_START;
	if (input_stream->msg != NULL) belle_sip_object_unref(input_stream->msg);
	input_stream->msg=NULL;
	input_stream->chuncked_mode=FALSE;
	input_stream->content_length=-1;
}

static size_t belle_sip_channel_input_stream_get_buff_length(belle_sip_channel_input_stream_t* input_stream) {
	return sizeof(input_stream->buff) - (input_stream->write_ptr-input_stream->buff);
}

111
static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
112
	belle_sip_channel_input_stream_reset(&obj->input_stream);
113
	if (obj->peer_list) bctbx_freeaddrinfo(obj->peer_list);
114
	if (obj->peer_cname) belle_sip_free(obj->peer_cname);
115
	belle_sip_free(obj->peer_name);
116
	if (obj->local_ip) belle_sip_free(obj->local_ip);
117 118 119
	obj->state_listeners=for_each_weak_unref_free(obj->state_listeners,(belle_sip_object_destroy_notify_t)channel_remove_listener,obj);
	obj->full_listeners=for_each_weak_unref_free(obj->full_listeners,(belle_sip_object_destroy_notify_t)channel_remove_listener,obj);

120 121
	if (obj->resolver_ctx != NULL) {
		belle_sip_resolver_context_cancel(obj->resolver_ctx);
122
		belle_sip_object_unref(obj->resolver_ctx);
123
	}
124 125 126 127
	if (obj->inactivity_timer){
		belle_sip_main_loop_remove_source(obj->stack->ml,obj->inactivity_timer);
		belle_sip_object_unref(obj->inactivity_timer);
	}
128 129 130 131
	if (obj->dns_ttl_timer) {
		belle_sip_main_loop_remove_source(obj->stack->ml, obj->dns_ttl_timer);
		belle_sip_object_unref(obj->dns_ttl_timer);
	}
132
	if (obj->public_ip) belle_sip_free(obj->public_ip);
133
	if (obj->outgoing_messages) belle_sip_list_free_with_data(obj->outgoing_messages,belle_sip_object_unref);
134
	if (obj->incoming_messages) belle_sip_list_free_with_data(obj->incoming_messages,belle_sip_object_unref);
135 136 137 138 139
	free_ewouldblock_buffer(obj);
	if (obj->cur_out_message){
		belle_sip_object_unref(obj->cur_out_message);
		obj->cur_out_message=NULL;
	}
140 141 142
	channel_end_send_background_task(obj);
	channel_end_recv_background_task(obj);
	/*normally this should do nothing because it sould have been terminated already,
143
		however leaving a background task open is so dangerous that we have to be paranoid*/
144
	belle_sip_message("Channel [%p] destroyed",obj);
145 146
}

147 148
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_channel_t);

149
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_channel_t)
150
	{
151
		BELLE_SIP_VPTR_INIT(belle_sip_channel_t,belle_sip_source_t,FALSE),
152 153
		(belle_sip_object_destroy_t)belle_sip_channel_destroy,
		NULL, /*clone*/
154
		NULL, /*marshal*/
155 156
		NULL, /*on_first_ref*/
		NULL, /*on_last_ref*/
157 158 159 160 161 162 163 164
		BELLE_SIP_DEFAULT_BUFSIZE_HINT
	},
	NULL, /* transport */
	0, /* reliable */
	NULL, /* connect */
	NULL, /* channel_send */
	NULL, /* channel_recv */
	NULL /* close */
165
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
166

jehan's avatar
jehan committed
167 168 169 170
static void fix_incoming_via(belle_sip_request_t *msg, const struct addrinfo* origin){
	char received[NI_MAXHOST];
	char rport[NI_MAXSERV];
	belle_sip_header_via_t *via;
171
	int err;
172 173
	struct sockaddr_storage saddr;
	socklen_t slen=sizeof(saddr);
174

jehan's avatar
jehan committed
175 176 177 178
	if (!origin) {
		belle_sip_warning("cannot fix via for message [%p], probably a test",msg);
		return;
	}
179
	bctbx_sockaddr_remove_v4_mapping(origin->ai_addr, (struct sockaddr*)&saddr, &slen);
180
	err=bctbx_getnameinfo((struct sockaddr*)&saddr,slen,received,sizeof(received),
jehan's avatar
jehan committed
181 182 183 184 185 186 187
	                rport,sizeof(rport),NI_NUMERICHOST|NI_NUMERICSERV);
	if (err!=0){
		belle_sip_error("fix_via: getnameinfo() failed: %s",gai_strerror(errno));
		return;
	}
	via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)msg,"via"));
	if (via){
188
		const char* host = belle_sip_header_via_get_host(via);
189

190 191
		if (strcmp(host,received)!=0)
				belle_sip_header_via_set_received(via,received);
192

193 194 195 196 197
		if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(via),"rport")){
			int port = belle_sip_header_via_get_listening_port(via);
			int rport_int=atoi(rport);
			if (rport_int!=port) belle_sip_header_via_set_rport(via,atoi(rport));
		}
jehan's avatar
jehan committed
198 199
	}
}
200

jehan's avatar
jehan committed
201 202 203 204 205
/*token       =  1*(alphanum / "-" / "." / "!" / "%" / "*"
                     / "_" / "+" / "`" / "'" / "~" )
 *
 * */
static int is_token(const char* buff,size_t bufflen ) {
206
	size_t i;
jehan's avatar
jehan committed
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
	for (i=0; i<bufflen && buff[i]!='\0';i++) {
		switch(buff[i]) {
			case '-' :
			case '.' :
			case '!' :
			case '%' :
			case '*' :
			case '_' :
			case '+' :
			case '`' :
			case '\'' :
			case '~' :
				break;
		default:
			if ((buff[i]>='0' && buff[i]<='9')
				|| (buff[i]>='A' && buff[i]<='Z')
				|| (buff[i]>='a' && buff[i]<='z')
				|| (buff[i]=='\0'))
				continue;
			else
				return 0;
		}
	}
	return 1;
}
jehan's avatar
jehan committed
232
static int get_message_start_pos(char *buff, size_t bufflen) {
Simon Morlat's avatar
Simon Morlat committed
233
	/*FIXME still to optimize and better test, specially REQUEST PATH and error path*/
jehan's avatar
jehan committed
234 235 236
	int i;
	int res=0;
	int status_code;
Simon Morlat's avatar
Simon Morlat committed
237
	char method[17]={0};
jehan's avatar
jehan committed
238
	char saved_char1;
Simon Morlat's avatar
Simon Morlat committed
239
	char sip_version[10]={0};
240
	size_t saved_char1_index;
241

242
	for(i=0; i<(int)bufflen-12;i++) { /*9=strlen( SIP/2.0\r\n)*/
jehan's avatar
jehan committed
243 244 245
		switch (buff[i]) { /*to avoid this character to be ignored by scanf*/
			case '\r':
			case '\n':
246 247
			case ' ' :
			case '\t':
jehan's avatar
jehan committed
248 249 250 251
				continue;
			default:
				break;
		}
jehan's avatar
jehan committed
252 253 254
		saved_char1_index=bufflen-1;
		saved_char1=buff[saved_char1_index]; /*make sure buff is null terminated*/
		buff[saved_char1_index]='\0';
jehan's avatar
jehan committed
255
		res=sscanf(buff+i,"SIP/2.0 %d ",&status_code);
jehan's avatar
jehan committed
256
		if (res!=1) res=sscanf(buff+i,"HTTP/1.%*i %d ",&status_code); /*might be HTTP ?*/
jehan's avatar
jehan committed
257
		if (res!=1) {
258
			res= sscanf(buff+i,"%16s %*s %9s\r\n",method,sip_version)==2
jehan's avatar
jehan committed
259
					&& is_token(method,sizeof(method))
Simon Morlat's avatar
Simon Morlat committed
260
					&& (strcmp("SIP/2.0",sip_version)==0 || strncmp("HTTP/1.",sip_version,strlen("HTTP/1."))==0);
jehan's avatar
jehan committed
261
		}
jehan's avatar
jehan committed
262 263
		buff[saved_char1_index]=saved_char1;
		if (res==1) return i;
jehan's avatar
jehan committed
264
	}
jehan's avatar
jehan committed
265 266 267
	return -1;
}

268 269 270 271
void belle_sip_channel_set_public_ip_port(belle_sip_channel_t *obj, const char *public_ip, int port){
	if (obj->public_ip){
		int ip_changed=0;
		int port_changed=0;
272

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
		if (public_ip && strcmp(obj->public_ip,public_ip)!=0){
			ip_changed=1;
		}
		if (port!=obj->public_port){
			port_changed=1;
		}
		if (ip_changed || port_changed){
			belle_sip_warning("channel [%p]: public ip is changed from [%s:%i] to [%s:%i]",obj,obj->public_ip,obj->public_port,public_ip,port);
		}
		belle_sip_free(obj->public_ip);
		obj->public_ip=NULL;
	}else if (public_ip){
		belle_sip_message("channel [%p]: discovered public ip and port are [%s:%i]",obj,public_ip,port);
	}
	if (public_ip){
		obj->public_ip=belle_sip_strdup(public_ip);
	}
	obj->public_port=port;
}

static void belle_sip_channel_learn_public_ip_port(belle_sip_channel_t *obj, belle_sip_response_t *resp){
	belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(resp,belle_sip_header_via_t);
	const char *received;
	int rport;
297

298 299 300 301
	if (!via){
		belle_sip_error("channel [%p]: no via in response.",obj);
		return;
	}
302 303 304 305 306

	if (!(received=belle_sip_header_via_get_received(via))) {
		/*use address from via*/;
		received=belle_sip_header_via_get_host(via);
	}
307

308 309 310 311
	rport=belle_sip_header_via_get_rport(via);
	if (rport<=0){
		/* no rport, the via port might be good then*/
		rport=belle_sip_header_via_get_listening_port(via);
312
	}
313 314
	belle_sip_channel_set_public_ip_port(obj,received,rport);

315
	obj->learnt_ip_port=TRUE;
316 317
}

318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
static void uncompress_body_if_required(belle_sip_message_t *msg) {
	belle_sip_body_handler_t *bh = belle_sip_message_get_body_handler(msg);
	belle_sip_memory_body_handler_t *mbh = NULL;
	belle_sip_header_t *ceh = NULL;
	size_t body_len = 0;

	if (bh != NULL) {
		body_len = belle_sip_message_get_body_size(msg);
		ceh = belle_sip_message_get_header(msg, "Content-Encoding");
	}
	if ((body_len > 0) && (ceh != NULL)) {
		const char *content_encoding = belle_sip_header_get_unparsed_value(ceh);
		if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(bh, belle_sip_memory_body_handler_t)) {
			mbh = BELLE_SIP_MEMORY_BODY_HANDLER(bh);
			if (belle_sip_memory_body_handler_unapply_encoding(mbh, content_encoding) == 0) {
333
				belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t);
334
				belle_sip_message_remove_header_from_ptr(msg, ceh);
335 336 337 338 339 340 341 342 343 344
				if (content_type
					&& (strcmp(belle_sip_header_content_type_get_type(content_type), "multipart") == 0)) {
					const char *unparsed_value = belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(content_type));
					const char *boundary = strstr(unparsed_value, ";boundary=");
					if (boundary != NULL) boundary += 10;
					if (boundary[0] == '\0') boundary = NULL;
					bh = (belle_sip_body_handler_t *)belle_sip_multipart_body_handler_new_from_buffer(
						belle_sip_memory_body_handler_get_buffer(mbh), belle_sip_body_handler_get_size((belle_sip_body_handler_t *)mbh), boundary);
					belle_sip_message_set_body_handler(msg, bh);
				}
345 346 347 348 349 350 351
			}
		} else {
			belle_sip_warning("message [%p] has Content-Encoding [%s] that cannot be unapplied", msg, content_encoding);
		}
	}
}

352
static void belle_sip_channel_message_ready(belle_sip_channel_t *obj){
353
	belle_sip_message_t *msg=obj->input_stream.msg;
354 355
	belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg);
	if (bh) belle_sip_body_handler_end_transfer(bh);
356
	if (belle_sip_message_is_response(msg)) belle_sip_channel_learn_public_ip_port(obj,BELLE_SIP_RESPONSE(msg));
357
	uncompress_body_if_required(msg);
358
	obj->incoming_messages=belle_sip_list_append(obj->incoming_messages,belle_sip_object_ref(msg));
359
	obj->stop_logging_buffer=0;
360
	belle_sip_channel_input_stream_reset(&obj->input_stream);
361 362
}

363 364 365 366 367 368 369 370
static void feed_body(belle_sip_channel_t *obj, size_t len){
	belle_sip_message_t *msg=obj->input_stream.msg;
	belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg);
	belle_sip_body_handler_recv_chunk(bh,msg,(uint8_t*)obj->input_stream.read_ptr,len);
	obj->input_stream.read_ptr+=len;
	belle_sip_channel_input_stream_rewind(&obj->input_stream);
}

371 372 373 374
/*returns TRUE if a body is expected, and initialize a few things in the input stream context*/
static int check_body(belle_sip_channel_t *obj){
	belle_sip_message_t *msg=obj->input_stream.msg;
	belle_sip_header_content_length_t* content_length_header = belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t);
375
	int expect_body=FALSE;
376

377
	obj->input_stream.content_length= content_length_header ? belle_sip_header_content_length_get_content_length(content_length_header) : 0;
378

379 380 381 382
	expect_body=obj->input_stream.content_length>0;
	
	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_http_response_t) || BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_http_request_t)){
		/*http chunked mode handling*/
383 384
		if (belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t)!=NULL){
			belle_sip_header_t *transfer_encoding=belle_sip_message_get_header(msg,"Transfer-Encoding");
385

386 387 388 389 390 391
			if (transfer_encoding){
				const char *value=belle_sip_header_get_unparsed_value(transfer_encoding);
				if (strstr(value,"chunked")!=0){
					obj->input_stream.chuncked_mode=1;
					obj->input_stream.content_length=0;
					obj->input_stream.chunk_size=-1;
392
					obj->input_stream.chunk_read_size=0;
393 394
				}
			}
395
			expect_body=TRUE;
396
		}
397
	}
398 399 400
	if (expect_body){
		belle_sip_body_handler_t *bh;
		/*should notify the listeners*/
401
		BELLE_SIP_CHANNEL_INVOKE_MESSAGE_HEADERS_LISTENERS(obj,msg);
402 403
		/*check if the listener has setup a body handler, otherwise create a default one*/
		if ((bh=belle_sip_message_get_body_handler(msg))==NULL){
404
			belle_sip_header_t *content_encoding = belle_sip_message_get_header(msg, "Content-Encoding");
405
			belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t);
406 407 408
			if (content_encoding != NULL) {
				belle_sip_message_set_body_handler(msg, (bh = (belle_sip_body_handler_t *)belle_sip_memory_body_handler_new(NULL, NULL)));
			} else if (content_type
409 410 411 412 413 414 415 416 417 418
				&& (strcmp(belle_sip_header_content_type_get_type(content_type), "multipart") == 0)) {
				const char *unparsed_value = belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(content_type));
				const char *boundary = strstr(unparsed_value, ";boundary=");
				if (boundary != NULL) boundary += 10;
				if (boundary[0] == '\0') boundary = NULL;
				belle_sip_message_set_body_handler(msg, (bh = (belle_sip_body_handler_t *)belle_sip_multipart_body_handler_new(belle_sip_multipart_body_handler_progress_cb, NULL, NULL, boundary)));
				belle_sip_body_handler_set_size(bh, obj->input_stream.content_length);
			} else {
				belle_sip_message_set_body_handler(msg,(bh=(belle_sip_body_handler_t*)belle_sip_memory_body_handler_new(NULL,NULL)));
			}
419
		}
420
		belle_sip_body_handler_begin_recv_transfer(bh);
421 422
	}
	return expect_body;
423 424
}

425
static int acquire_body_simple(belle_sip_channel_t *obj, int end_of_stream){
426
	size_t content_length=obj->input_stream.content_length;
427 428 429 430
	size_t to_read=obj->input_stream.write_ptr-obj->input_stream.read_ptr;
	belle_sip_message_t *msg=obj->input_stream.msg;
	belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg);
	size_t cursize=belle_sip_body_handler_get_transfered_size(bh);
431

432 433 434 435 436 437 438 439 440
	if ((cursize == 0) && (to_read == 0)) {
		/**
		 * No data has been received yet, so do not call feed_body() with a size
		 * of 0 that is meaning that the transfer is finished.
		 */
	} else {
		to_read=MIN(content_length-cursize, to_read);
		feed_body(obj,to_read);
	}
441 442

	if (end_of_stream ||  belle_sip_body_handler_get_transfered_size(bh)>=content_length){
443 444
		/*great body completed*/
		belle_sip_message("channel [%p] read [%i] bytes of body from [%s:%i]"	,obj
François Grisez's avatar
François Grisez committed
445
			,(int)content_length
446
			,obj->peer_name
447
			,obj->peer_port);
448 449 450
		belle_sip_channel_message_ready(obj);
		return BELLE_SIP_CONTINUE;
	}
451 452
	/*body is not finished, we need more data*/
	return BELLE_SIP_STOP;
453 454
}

455
static int acquire_chuncked_body(belle_sip_channel_t *obj){
456
	belle_sip_channel_input_stream_t *st=&obj->input_stream;
457
	int readsize;
458 459 460
	do{
		if (st->chunk_size==-1){
			char *tmp;
461
			/*belle_sip_message("seeing: %s",st->read_ptr);*/
462 463 464
			while ( (tmp=strstr(st->read_ptr,"\r\n"))==st->read_ptr){/*skip \r\n*/
				st->read_ptr+=2;
			}
465

466 467 468 469 470 471 472 473 474 475 476
			if (tmp!=NULL){
				/*the chunk length is there*/
				long chunksize=strtol(st->read_ptr,NULL,16);
				if (chunksize>=0 && chunksize!=LONG_MAX){
					if (chunksize==0){
						belle_sip_message("Got end of chunked body");
						st->read_ptr=tmp+4; /*last chunk indicator finishes with two \r\n*/
						if (st->read_ptr>st->write_ptr) st->read_ptr=st->write_ptr;
						belle_sip_channel_message_ready(obj);
						return BELLE_SIP_CONTINUE;
					}else{
477
						belle_sip_message("Will get a chunk of %i bytes",(int)chunksize);
478
						st->chunk_size=chunksize;
479
						st->chunk_read_size=0;
480 481 482 483 484 485 486 487 488 489 490 491
						st->read_ptr=tmp+2;
					}
				}else{
					belle_sip_error("Chunk parse error");
					belle_sip_channel_input_stream_reset(st);
					return BELLE_SIP_CONTINUE;
				}
			}else{
				/*need more data*/
				return BELLE_SIP_STOP;
			}
		}
492
		readsize=MIN((int)(st->write_ptr-st->read_ptr),st->chunk_size-st->chunk_read_size);
493 494 495 496 497
		if (readsize>0){
			feed_body(obj,readsize);
			st->chunk_read_size+=readsize;
		}
		if (st->chunk_size==st->chunk_read_size){
498 499 500 501 502 503 504 505
			/*we have a chunk completed*/
			st->content_length+=st->chunk_size;
			belle_sip_message("Chunk of [%i] bytes completed",st->chunk_size);
			st->chunk_size=-1;/*wait for next chunk indicator*/
		}else{
			/*need more data*/
			return BELLE_SIP_STOP;
		}
506 507
	}while(st->write_ptr-st->read_ptr>0); /*no need to continue if nothing to read*/
	return BELLE_SIP_STOP;
508 509 510 511
}

static int acquire_body(belle_sip_channel_t *obj, int end_of_stream){
	if (obj->input_stream.chuncked_mode)
512
		return acquire_chuncked_body(obj);
513 514 515
	else return acquire_body_simple(obj,end_of_stream);
}

516 517
static void notify_incoming_messages(belle_sip_channel_t *obj){
	belle_sip_list_t *elem,*l_it;
518 519
	
	belle_sip_list_t *listeners=belle_sip_list_copy_with_data(obj->full_listeners,(void *(*)(void*))belle_sip_object_ref);
520

521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
	for(l_it=listeners;l_it!=NULL;l_it=l_it->next){
		belle_sip_channel_listener_t *listener=(belle_sip_channel_listener_t*)l_it->data;
		for(elem=obj->incoming_messages;elem!=NULL;elem=elem->next){
			belle_sip_message_t *msg=(belle_sip_message_t*)elem->data;
			BELLE_SIP_INTERFACE_METHODS_TYPE(belle_sip_channel_listener_t) *methods;
			methods=BELLE_SIP_INTERFACE_GET_METHODS(listener,belle_sip_channel_listener_t);
			if (methods->on_message)
				methods->on_message(listener,obj,msg);
		}
	}
	belle_sip_list_free_with_data(listeners,belle_sip_object_unref);
	belle_sip_list_free_with_data(obj->incoming_messages,belle_sip_object_unref);
	obj->incoming_messages=NULL;
}

536
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj, int end_of_stream){
jehan's avatar
jehan committed
537
	int offset;
538
	size_t read_size=0;
539
	int num;
540

541
	while ((num=(int)(obj->input_stream.write_ptr-obj->input_stream.read_ptr))>0){
542

jehan's avatar
jehan committed
543
		if (obj->input_stream.state == WAITING_MESSAGE_START) {
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
			int i;
			/*first, make sure there is \r\n in the buffer, otherwise, micro parser cannot conclude, because we need a complete request or response line somewhere*/
			for (i=0;i<num-1;i++) {
				if ((obj->input_stream.read_ptr[i]=='\r' && obj->input_stream.read_ptr[i+1]=='\n')
						|| belle_sip_channel_input_stream_get_buff_length(&obj->input_stream) <= 1 /*1 because null terminated*/  /*if buffer full try to parse in any case*/) {
					/*good, now we can start searching  for request/response*/
					if ((offset=get_message_start_pos(obj->input_stream.read_ptr,num)) >=0 ) {
						/*message found !*/
						if (offset>0) {
							belle_sip_warning("trashing [%i] bytes in front of sip message on channel [%p]",offset,obj);
							obj->input_stream.read_ptr+=offset;
						}
						obj->input_stream.state=MESSAGE_AQUISITION;
					} else {
						belle_sip_debug("Unexpected [%s] received on channel [%p], trashing",obj->input_stream.read_ptr,obj);
						obj->input_stream.read_ptr=obj->input_stream.write_ptr;
						belle_sip_channel_input_stream_reset(&obj->input_stream);
						continue;
					}
				break;
jehan's avatar
jehan committed
564
				}
565 566 567 568 569
			}

			if (i >= num-1) {
				belle_sip_debug("[%s] received on channel [%p], cannot determine if expected or not, waiting for new data",obj->input_stream.read_ptr,obj);
				break;
jehan's avatar
jehan committed
570 571 572 573 574
			}
		}

		if (obj->input_stream.state==MESSAGE_AQUISITION) {
			/*search for \r\n\r\n*/
jehan's avatar
jehan committed
575 576
			char* end_of_message=NULL;
			if ((end_of_message=strstr(obj->input_stream.read_ptr,"\r\n\r\n"))){
577 578
				int bytes_to_parse;
				char tmp;
579
				/*end of message found*/
jehan's avatar
jehan committed
580
				end_of_message+=4;/*add \r\n\r\n*/
581
				bytes_to_parse=(int)(end_of_message-obj->input_stream.read_ptr);
582 583
				tmp=*end_of_message;
				*end_of_message='\0';/*this is in order for the following log to print the message only to its end.*/
584
				/*belle_sip_message("channel [%p] read message of [%i] bytes:\n%.40s...",obj, bytes_to_parse, obj->input_stream.read_ptr);*/
585
				obj->input_stream.msg=belle_sip_message_parse_raw(obj->input_stream.read_ptr
586
										,bytes_to_parse
587
										,&read_size);
588
				*end_of_message=tmp;
589 590
				obj->input_stream.read_ptr+=read_size;
				if (obj->input_stream.msg && read_size > 0){
591
					belle_sip_message("channel [%p] [%i] bytes parsed",obj,(int)read_size);
592 593 594
					belle_sip_object_ref(obj->input_stream.msg);
					if (belle_sip_message_is_request(obj->input_stream.msg)) fix_incoming_via(BELLE_SIP_REQUEST(obj->input_stream.msg),obj->current_peer);
					/*check for body*/
595

596
					if (check_body(obj)){
597 598 599 600 601
						obj->input_stream.state=BODY_AQUISITION;
					} else {
						/*no body*/
						belle_sip_channel_message_ready(obj);
						continue;
jehan's avatar
jehan committed
602
					}
603
				}else{
jehan's avatar
jehan committed
604
					belle_sip_error("Could not parse [%s], on channel [%p] skipping to [%s]",obj->input_stream.read_ptr
605 606
														,obj
														,end_of_message);
jehan's avatar
jehan committed
607 608
					obj->input_stream.read_ptr=end_of_message;
					obj->input_stream.state=WAITING_MESSAGE_START;
609
					continue;
jehan's avatar
jehan committed
610
				}
611
			}else break; /*The message isn't finished to be receive, we need more data*/
jehan's avatar
jehan committed
612 613 614
		}

		if (obj->input_stream.state==BODY_AQUISITION) {
615
			if (acquire_body(obj,end_of_stream)==BELLE_SIP_STOP) break;
jehan's avatar
jehan committed
616
		}
617 618 619
	}
}

620 621
static void belle_sip_channel_process_stream(belle_sip_channel_t *obj, int eos){
	belle_sip_channel_parse_stream(obj,eos);
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
	if (obj->incoming_messages) {
		if (obj->simulated_recv_return == 1500) {
			belle_sip_list_t *elem;
			for(elem=obj->incoming_messages;elem!=NULL;elem=elem->next){
				belle_sip_message_t *msg=(belle_sip_message_t*)elem->data;
				char* dump = belle_sip_message_to_string(msg);
				belle_sip_message("Silently discarding incoming message [%.50s...] on channel [%p]",dump, obj);
				belle_sip_free(dump);
			}
			belle_sip_list_free_with_data(obj->incoming_messages,belle_sip_object_unref);
			obj->incoming_messages=NULL;
		} else {
			notify_incoming_messages(obj);
		}
	}
637 638 639
}

static int belle_sip_channel_process_read_data(belle_sip_channel_t *obj){
640
	int num;
641
	int ret=BELLE_SIP_CONTINUE;
642

643
	/*prevent system to suspend the process until we have finish reading everything from the socket and notified the upper layer*/
644
	if (obj->input_stream.state == WAITING_MESSAGE_START) {
645
		channel_begin_recv_background_task(obj);
646
	}
647

648 649
	if (obj->simulated_recv_return>0) {
		num=belle_sip_channel_recv(obj,obj->input_stream.write_ptr,belle_sip_channel_input_stream_get_buff_length(&obj->input_stream)-1);
650
	} else {
651 652
		belle_sip_message("channel [%p]: simulating recv() returning %i",obj,obj->simulated_recv_return);
		num=obj->simulated_recv_return;
653 654
	}
	if (num>0){
655
		char *begin=obj->input_stream.write_ptr;
656 657 658
		obj->input_stream.write_ptr+=num;
		/*first null terminate the read buff*/
		*obj->input_stream.write_ptr='\0';
jehan's avatar
jehan committed
659
		if (num>20 || obj->input_stream.state != WAITING_MESSAGE_START ) /*to avoid tracing server based keep alives*/ {
660
			char *logbuf = make_logbuf(obj, BELLE_SIP_LOG_MESSAGE ,begin,num);
661 662 663 664 665 666 667 668 669 670
			if (logbuf) {
				belle_sip_message("channel [%p]: received [%i] new bytes from [%s://%s:%i]:\n%s",
						obj,
						num,
						belle_sip_channel_get_transport_name(obj),
						obj->peer_name,
						obj->peer_port,
						logbuf);
				belle_sip_free(logbuf);
			}
jehan's avatar
jehan committed
671
		}
672
		belle_sip_channel_process_stream(obj,FALSE);
673 674 675
		if (obj->input_stream.state == WAITING_MESSAGE_START){
			channel_end_recv_background_task(obj);
		}/*if still in message acquisition state, keep the backgroud task*/
jehan's avatar
jehan committed
676
	} else if (num == 0) {
677
		/*before closing the channel, check if there was a pending message to receive, whose body acquisition is to be finished.*/
678
		belle_sip_channel_process_stream(obj,TRUE);
679
		obj->closed_by_remote = TRUE;
jehan's avatar
jehan committed
680
		channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
681
		ret=BELLE_SIP_STOP;
682 683
	} else if (belle_sip_error_code_is_would_block(-num)){
		belle_sip_message("channel [%p]: recv() EWOULDBLOCK",obj);
684
		ret=BELLE_SIP_CONTINUE;
685
	}else{
jehan's avatar
jehan committed
686
		belle_sip_error("Receive error on channel [%p]",obj);
jehan's avatar
jehan committed
687
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
688
		ret=BELLE_SIP_STOP;
jehan's avatar
jehan committed
689
	}
690
	return ret;
691
}
692

693 694
int belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents){
	int ret=BELLE_SIP_CONTINUE;
695
	belle_sip_object_ref(obj);
696 697 698 699 700 701
	if (revents & BELLE_SIP_EVENT_READ) {
		int rret=belle_sip_channel_process_read_data(obj);
		if (rret==BELLE_SIP_STOP) ret=BELLE_SIP_STOP;
	}
	if (revents & BELLE_SIP_EVENT_WRITE){
		/*if we are here, this is because we had an EWOULDBLOCK while sending a message*/
702 703
		/*continue to send pending messages but before check the channel is still alive because
		it may have been closed by belle_sip_channel_process_read_data() above.*/
704 705 706
		if (obj->state == BELLE_SIP_CHANNEL_READY){
			channel_process_queue(obj);
		}
707
	}
708
	belle_sip_object_unref(obj);
709 710 711
	return ret;
}

712 713
static int channel_inactive_timeout(void *data, unsigned int event){
	belle_sip_channel_t *obj=(belle_sip_channel_t *)data;
714
	belle_sip_message("Channel [%p]: inactivity timeout reached.",obj);
715 716 717 718
	channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
	return BELLE_SIP_STOP;
}

719
static void update_inactivity_timer(belle_sip_channel_t *obj, int from_recv){
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
	int inactive_timeout=belle_sip_stack_get_inactive_transport_timeout(obj->stack)*1000;
	if (inactive_timeout>0){
		if (!obj->inactivity_timer ){
			obj->inactivity_timer=belle_sip_main_loop_create_timeout(obj->stack->ml,channel_inactive_timeout,obj,inactive_timeout,"Channel inactivity timer");
		}else{
			/*restart the timer for new period*/
			belle_sip_source_set_timeout(obj->inactivity_timer,inactive_timeout);
		}
	}else{
		if (obj->inactivity_timer){
			belle_sip_main_loop_remove_source(obj->stack->ml,obj->inactivity_timer);
			belle_sip_object_unref(obj->inactivity_timer);
			obj->inactivity_timer=NULL;
		}
	}
735 736
	if (from_recv)
		obj->last_recv_time=belle_sip_time_ms();
737
}
jehan's avatar
jehan committed
738

739 740 741 742 743 744 745
/*constructor for channels creating an outgoing connection
 * bindip local ip address to bind on, typically 0.0.0.0 or ::0
 * locaport locaport to use for binding, can be set to 0 if port doesn't matter
 * peer_cname canonical name of remote host, used for TLS verification
 * peername peer's hostname, either ip address or DNS name
 * pee_port peer's port to connect to.
 */
746
void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack,const char *bindip,int localport,const char *peer_cname, const char *peername, int peer_port){
747 748
	/*to initialize our base class:*/
	belle_sip_channel_set_socket(obj,-1,NULL);
749

750
	/*then initialize members*/
751
	obj->ai_family=AF_INET;
752
	obj->peer_cname=peer_cname ? belle_sip_strdup(peer_cname) : NULL;
753 754
	obj->peer_name=belle_sip_strdup(peername);
	obj->peer_port=peer_port;
755
	obj->stack=stack;
756 757 758 759 760 761
	if (bindip){
		if (strcmp(bindip,"::0")!=0 && strcmp(bindip,"0.0.0.0")!=0)
			obj->local_ip=belle_sip_strdup(bindip);
		if (strchr(bindip,':')!=NULL)
			obj->ai_family=AF_INET6;
	}
762
	obj->local_port=localport;
Simon Morlat's avatar
Simon Morlat committed
763
	obj->simulated_recv_return=1;/*not set*/
764 765
	if (peername){
		/*check if we are given a real dns name or just an ip address*/
766
		struct addrinfo *ai=bctbx_ip_address_to_addrinfo(AF_UNSPEC,SOCK_STREAM,peername,peer_port);
767
		if (ai) bctbx_freeaddrinfo(ai);
768 769
		else obj->has_name=TRUE;
	}
770
	belle_sip_channel_input_stream_reset(&obj->input_stream);
771
	update_inactivity_timer(obj,FALSE);
772 773
}

774
/*constructor for channels created by incoming connections*/
775
void belle_sip_channel_init_with_addr(belle_sip_channel_t *obj, belle_sip_stack_t *stack, const char *bindip, int localport, const struct sockaddr *peer_addr, socklen_t addrlen){
776 777 778
	char remoteip[64];
	struct addrinfo ai;
	int peer_port;
779

780 781 782 783
	memset(&ai,0,sizeof(ai));
	ai.ai_family=peer_addr->sa_family;
	ai.ai_addr=(struct sockaddr*)peer_addr;
	ai.ai_addrlen=addrlen;
784
	bctbx_addrinfo_to_ip_address(&ai,remoteip,sizeof(remoteip),&peer_port);
785
	belle_sip_channel_init(obj,stack,bindip,localport,NULL,remoteip,peer_port);
786
	obj->peer_list=obj->current_peer=bctbx_ip_address_to_addrinfo(ai.ai_family, ai.ai_socktype, obj->peer_name,obj->peer_port);
787
	obj->ai_family=ai.ai_family;
788 789
}

790
void belle_sip_channel_set_socket(belle_sip_channel_t *obj, belle_sip_socket_t sock, belle_sip_source_func_t datafunc){
jehan's avatar
jehan committed
791 792 793 794 795 796
	belle_sip_socket_source_init((belle_sip_source_t*)obj
									, datafunc
									, obj
									, sock
									, BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_WRITE
									, -1);
797 798
}

799 800 801 802 803
static bool_t is_state_only_listener(const belle_sip_channel_listener_t *listener) {
	BELLE_SIP_INTERFACE_METHODS_TYPE(belle_sip_channel_listener_t) *methods;
	methods=BELLE_SIP_INTERFACE_GET_METHODS(listener,belle_sip_channel_listener_t);
	return methods->on_state_changed && !(methods->on_message_headers || methods->on_message || methods->on_sending || methods->on_auth_requested);
}
804
static void channel_remove_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
805 806 807 808 809
	if (is_state_only_listener(l))
		obj->state_listeners=belle_sip_list_remove(obj->state_listeners,l);
	else
		obj->full_listeners=belle_sip_list_remove(obj->full_listeners,l);

810 811
}

812
void belle_sip_channel_add_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
813 814 815 816 817 818 819 820 821 822 823
	
	if (is_state_only_listener(l)) {
		obj->state_listeners=belle_sip_list_prepend(obj->state_listeners,
												   belle_sip_object_weak_ref(l,
																	   (belle_sip_object_destroy_notify_t)channel_remove_listener,obj));
	} else {
		obj->full_listeners=belle_sip_list_prepend(obj->full_listeners,
													belle_sip_object_weak_ref(l,
																		(belle_sip_object_destroy_notify_t)channel_remove_listener,obj));
	}
	
824 825 826
}

void belle_sip_channel_remove_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
827 828
	belle_sip_object_weak_unref(l,(belle_sip_object_destroy_notify_t)channel_remove_listener,obj);
	channel_remove_listener(obj,l);
829 830
}

831
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const belle_sip_hop_t *hop, const struct addrinfo *addr){
832
	if (hop && strcmp(hop->host,obj->peer_name)==0 && (hop->port==obj->peer_port || obj->srv_overrides_port)){
833 834
		if (hop->cname && obj->peer_cname && strcmp(hop->cname,obj->peer_cname)!=0)
			return 0; /*cname mismatch*/
835
		return 1;
836
	}
837
	if (addr && obj->current_peer)
838
		return bctbx_sockaddr_equals(addr->ai_addr,obj->current_peer->ai_addr);
839 840 841
	return 0;
}

842 843 844 845 846
const char *belle_sip_channel_get_local_address(belle_sip_channel_t *obj, int *port){
	if (port) *port=obj->local_port;
	return obj->local_ip;
}

847 848 849 850 851 852
const char *belle_sip_channel_get_public_address(belle_sip_channel_t *obj, int *port){
	const char *ret = obj->public_ip ? obj->public_ip : obj->local_ip;
	if (*port) *port= obj->public_port;
	return ret;
}

Simon Morlat's avatar
Simon Morlat committed
853 854 855 856
belle_sip_uri_t *belle_sip_channel_create_routable_uri(belle_sip_channel_t *chan) {
	const char *transport = belle_sip_channel_get_transport_name_lower_case(chan);
	belle_sip_uri_t* uri = belle_sip_uri_new();
	unsigned char natted = chan->public_ip && strcmp(chan->public_ip,chan->local_ip)!=0;
857

Simon Morlat's avatar
Simon Morlat committed
858 859 860 861
	if (natted) {
		belle_sip_uri_set_host(uri, chan->public_ip);
		belle_sip_uri_set_port(uri, chan->public_port);
	} else {
862

Simon Morlat's avatar
Simon Morlat committed
863 864 865 866 867 868
		belle_sip_uri_set_host(uri, chan->local_ip);
		// With streamed protocols listening port is what we want
		if (chan->lp)
			belle_sip_uri_set_port(uri, belle_sip_uri_get_port(chan->lp->listening_uri));
		else belle_sip_uri_set_port(uri,chan->local_port);
	}
869

Simon Morlat's avatar
Simon Morlat committed
870 871 872 873 874 875
	belle_sip_uri_set_transport_param(uri, transport);
	belle_sip_uri_set_lr_param(uri, TRUE);
	return uri;
}


876 877 878
int belle_sip_channel_is_reliable(const belle_sip_channel_t *obj){
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->reliable;
}
879

jehan's avatar
jehan committed
880 881 882 883 884 885 886 887 888 889 890
const char * belle_sip_channel_get_transport_name_lower_case(const belle_sip_channel_t *obj){
	const char* transport = belle_sip_channel_get_transport_name(obj);
	if (strcasecmp("udp",transport)==0) return "udp";
	else if (strcasecmp("tcp",transport)==0) return "tcp";
	else if (strcasecmp("tls",transport)==0) return "tls";
	else if (strcasecmp("dtls",transport)==0) return "dtls";
	else {
		belle_sip_message("Cannot convert [%s] to lower case",transport);
		return transport;
	}
}
891

892
const char * belle_sip_channel_get_transport_name(const belle_sip_channel_t *obj){
893
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->transport;
894 895 896
}

int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
897
	update_inactivity_timer(obj,FALSE);
898 899 900 901
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->channel_send(obj,buf,buflen);
}

int belle_sip_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
902
	update_inactivity_timer(obj,TRUE);
903 904 905
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->channel_recv(obj,buf,buflen);
}

906
void belle_sip_channel_close(belle_sip_channel_t *obj){
907
	if (BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->close)
908
		BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->close(obj); /*udp channel doesn't have close function*/
909
	/*removing the source (our base class) will decrement the ref count, this why this code needs to be protected by ref/unref.*/
910 911
	belle_sip_main_loop_remove_source(obj->stack->ml,(belle_sip_source_t*)obj);
	belle_sip_source_uninit((belle_sip_source_t*)obj);
912 913
}

914
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
915
	return obj->current_peer;
916 917
}

918 919 920
static void channel_on_send_background_task_ended(belle_sip_channel_t *obj){
	belle_sip_warning("channel [%p]: send background task has to be ended now, but work isn't finished.",obj);
	channel_end_send_background_task(obj);
921 922
}

923
static void channel_begin_send_background_task(belle_sip_channel_t *obj){
924
	if (obj->bg_task_id==0){
925
		obj->bg_task_id=belle_sip_begin_background_task("belle-sip send channel",(void (*)(void*))channel_on_send_background_task_ended, obj);
926
		if (obj->bg_task_id) belle_sip_message("channel [%p]: starting send background task with id=[%lx].",obj,obj->bg_task_id);
927
	}
928 929
}

930
static void channel_end_send_background_task(belle_sip_channel_t *obj){
931
	if (obj->bg_task_id){
932
		belle_sip_message("channel [%p]: ending send background task with id=[%lx].",obj,obj->bg_task_id);
933 934 935 936 937
		belle_sip_end_background_task(obj->bg_task_id);
		obj->bg_task_id=0;
	}
}

938 939 940 941 942 943 944
static void channel_on_recv_background_task_ended(belle_sip_channel_t *obj){
	belle_sip_warning("channel [%p]: recv background task has to be ended now, but work isn't finished.",obj);
	channel_end_recv_background_task(obj);
}

static void channel_begin_recv_background_task(belle_sip_channel_t *obj){
	if (obj->recv_bg_task_id==0){
945
		obj->recv_bg_task_id=belle_sip_begin_background_task("belle-sip recv channel",(void (*)(void*))channel_on_recv_background_task_ended, obj);
946
		if (obj->recv_bg_task_id) belle_sip_message("channel [%p]: starting recv background task with id=[%lx].",obj,obj->recv_bg_task_id);
947 948 949 950 951
	}
}

static void channel_end_recv_background_task(belle_sip_channel_t *obj){
	if (obj->recv_bg_task_id){
952
		belle_sip_message("channel [%p]: ending recv background task with id=[%lx].",obj,obj->recv_bg_task_id);
953 954 955 956 957
		belle_sip_end_background_task(obj->recv_bg_task_id);
		obj->recv_bg_task_id=0;
	}
}

Simon Morlat's avatar
Simon Morlat committed
958
static void channel_invoke_state_listener(belle_sip_channel_t *obj){
959 960 961 962
	int close = FALSE;
	switch(obj->state){
		case BELLE_SIP_CHANNEL_DISCONNECTED:
		case BELLE_SIP_CHANNEL_ERROR:
963
		/*the background tasks must be released "after" notifying the app of the disconnected or error state
964 965
		 By "after" it is means not before the main loop iteration that will notify the app.
		 This is the reason why these calls are done here rather than in the channel_set_state() function.*/
966 967
		channel_end_send_background_task(obj);
		channel_end_recv_background_task(obj);
968 969 970 971
		close = TRUE;
		break;
		default:
		break;
972
	}
973 974
	/*Channel listeners may drop the last reference of the channel, so protect by ref/unref until we finish.*/
	belle_sip_object_ref(obj);
975
	BELLE_SIP_CHANNEL_INVOKE_STATE_LISTENERS(obj,obj->state);
976
	if (close) belle_sip_channel_close(obj);
977
	belle_sip_object_unref(obj);
Simon Morlat's avatar
Simon Morlat committed
978 979
}

980 981 982 983 984 985 986
static void channel_notify_error_to_listeners(belle_sip_channel_t *obj){
	/* The channel may have been passed to DISCONNECTED state due to _force_close() method.
	 * Do not notify the error in this case, since the channel is already closed.
	 */
	if (obj->state == BELLE_SIP_CHANNEL_ERROR){
		channel_invoke_state_listener(obj);
	}
987 988 989
	belle_sip_object_unref(obj);
}

990
static void channel_connect_next(belle_sip_channel_t *obj){
991 992 993
	if (obj->state == BELLE_SIP_CHANNEL_RETRY){
		belle_sip_channel_connect(obj);
	}
994 995 996
	belle_sip_object_unref(obj);
}

997
static void belle_sip_channel_handle_error(belle_sip_channel_t *obj){
998 999 1000
	if (obj->state!=BELLE_SIP_CHANNEL_READY || obj->soft_error){
		/* Previous connection attempts were failed (channel could not get ready) OR soft error reported*/
		obj->soft_error = FALSE;
1001 1002 1003 1004 1005
		/* See if you can retry on an alternate ip address.*/
		if (obj->current_peer && obj->current_peer->ai_next){ /*obj->current_peer may be null in case of dns error*/
			obj->current_peer=obj->current_peer->ai_next;
			channel_set_state(obj,BELLE_SIP_CHANNEL_RETRY);
			belle_sip_channel_close(obj);
1006
			belle_sip_main_loop_do_later(obj->stack->ml,(belle_sip_callback_t)channel_connect_next,belle_sip_object_ref(obj));
1007 1008 1009
			return;
		}/*else we have already tried all the ip addresses, so give up and notify the error*/
	}/*else the channel was previously working good with the current ip address but now fails, so let's notify the error*/
1010

1011 1012
	obj->state=BELLE_SIP_CHANNEL_ERROR;
	/*Because error notification will in practice trigger the destruction of possible transactions and this channel,
1013 1014 1015
	* it is safer to invoke the listener outside the current call stack.
	* Indeed the channel encounters network errors while being called for transmiting by a transaction.
	*/
1016
	belle_sip_main_loop_do_later(obj->stack->ml,(belle_sip_callback_t)channel_notify_error_to_listeners,belle_sip_object_ref(obj));
1017 1018
}

1019 1020
int belle_sip_channel_notify_timeout(belle_sip_channel_t *obj){
	const int too_long=60;
1021 1022 1023 1024 1025 1026
	
	if (obj->state != BELLE_SIP_CHANNEL_READY){
		/*no need to notify the timeout if the channel is already in error or retry state*/
		return FALSE;
	}
	
1027
	if ((int)(belle_sip_time_ms() - obj->last_recv_time) >= (too_long * 1000)){
1028 1029 1030 1031 1032
		belle_sip_message("A timeout related to this channel occured and no message received during last %i seconds. This channel is suspect, moving to error state",too_long);
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
		return TRUE;
	}
	return FALSE;
Simon Morlat's avatar
Simon Morlat committed
1033 1034
}

1035 1036 1037 1038 1039 1040
void belle_sip_channel_notify_server_error(belle_sip_channel_t *obj){
	belle_sip_message("channel[%p]: this server is encountering internal errors, moving to error state to eventually connect to another IP.", obj);
	obj->soft_error = TRUE;
	channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
}

1041 1042
void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state) {
	belle_sip_message("channel %p: state %s",obj,belle_sip_channel_state_to_string(state));
1043

1044 1045 1046 1047
	if (state==BELLE_SIP_CHANNEL_ERROR){
		belle_sip_channel_handle_error(obj);
	}else{
		obj->state=state;
Simon Morlat's avatar
Simon Morlat committed
1048
		channel_invoke_state_listener(obj);
1049
	}
1050
}
1051

1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
static void free_ewouldblock_buffer(belle_sip_channel_t *obj){
	if (obj->ewouldblock_buffer){
		belle_sip_free(obj->ewouldblock_buffer);
		obj->ewouldblock_buffer=NULL;
		obj->ewouldblock_size=0;
		obj->ewouldblock_offset=0;
	}
}

static void handle_ewouldblock(belle_sip_channel_t *obj, const char *buffer, size_t size){
	belle_sip_source_set_events((belle_sip_source_t*)obj,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_WRITE|BELLE_SIP_EVENT_ERROR);
	free_ewouldblock_buffer(obj);
	obj->ewouldblock_buffer=belle_sip_malloc(size);
	obj->ewouldblock_size=size;
	memcpy(obj->ewouldblock_buffer,buffer,size);
}

1069
static size_t find_non_printable(const char *buffer, size_t size){
1070
#if 0
1071 1072
	size_t i;
	for(i=0;i<size;++i){
1073 1074
		/*we must check that character is printable, not just ascii
		(31 'US' char is not printable for instance)*/
1075 1076 1077 1078
#ifdef _MSC_VER
		if ((buffer[i] < 0) || (buffer[i] > 255)) return i;
#endif
		if (!isprint(buffer[i]) && !isspace(buffer[i])) return i;
1079 1080
	}
	return size;
1081 1082
#else
	size_t i=0;
1083 1084
	mbstate_t mbs;
	memset(&mbs, 0, sizeof(mbs));
1085
	do {
1086 1087
		size_t valid_multibyte_len = mbrlen(buffer+i, size-i, &mbs);
		if (valid_multibyte_len == (size_t)-1 || valid_multibyte_len == (size_t)-2 || valid_multibyte_len == 0) break;
1088 1089 1090 1091
		i += valid_multibyte_len;
	}while(1);
	return i;
#endif
1092 1093 1094 1095
}
/*
 * this function is to avoid logging too much or non-ascii data received.
 */
1096
static char *make_logbuf(belle_sip_channel_t *obj, belle_sip_log_level level, const char *buffer, size_t size){
1097 1098
	char *logbuf;
	char truncate_msg[128]={0};
1099
	size_t limit=7000; /*big message when many ice candidates*/
1100

1101
	if (!belle_sip_log_level_enabled(level)){
1102 1103 1104 1105
		return NULL;
	}
	if (obj->stop_logging_buffer == 1) {
		return NULL;
1106
	}
Simon Morlat's avatar
Simon Morlat committed
1107 1108 1109
	size = MIN(size,limit);
	limit=find_non_printable(buffer, size);
	if (limit < size) {
1110
		belle_sip_message("channel [%p]: found binary data in buffer, will stop logging it now.", obj);
1111
		obj->stop_logging_buffer = 1;
Simon Morlat's avatar
Simon Morlat committed
1112
		if (limit == 0){
1113 1114
			snprintf(truncate_msg,sizeof(truncate_msg)-1,"... (binary data)");
		} else {
1115
			snprintf(truncate_msg,sizeof(truncate_msg)-1,"... (first %u bytes shown)",(unsigned int)limit);
1116
		}
1117
	}
Simon Morlat's avatar
Simon Morlat committed
1118
	size = limit;
1119

Simon Morlat's avatar
Simon Morlat committed
1120
	size += strlen(truncate_msg);
1121

1122
	logbuf=belle_sip_malloc(size+1);
Simon Morlat's avatar
Simon Morlat committed
1123
	strncpy(logbuf, buffer, size);
1124
	if (truncate_msg[0]!=0){
Simon Morlat's avatar
Simon Morlat committed
1125
		strcpy(logbuf+limit,truncate_msg);
1126 1127 1128 1129 1130 1131
	}
	logbuf[size]='\0';
	return logbuf;
}

static int send_buffer(belle_sip_channel_t *obj, const char *buffer, size_t size){
1132
	int ret=0;
1133
	char *logbuf=NULL;
1134

jehan's avatar
jehan committed
1135
	if (obj->stack->send_error == 0){
1136
		ret=belle_sip_channel_send(obj,buffer,size);
jehan's avatar
jehan committed
1137
	}else if (obj->stack->send_error<0){
1138 1139
		/*for testing purpose only */
		ret=obj->stack->send_error;
jehan's avatar
jehan committed
1140
	} else {
1141
		ret=(int)size; /*to silently discard message*/
1142 1143 1144 1145
	}

	if (ret<0){
		if (!belle_sip_error_code_is_would_block(-ret)){
1146
			belle_sip_error("channel [%p]: could not send [%i] bytes from [%s://%s:%i] to [%s:%i]"	,obj
1147
				,(int)size
Simon Morlat's avatar
Simon Morlat committed
1148 1149 1150 1151 1152
				,belle_sip_channel_get_transport_name(obj)
				,obj->local_ip
				,obj->local_port
				,obj->peer_name
				,obj->peer_port);
1153
			channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
1154
		}/*ewouldblock error has to be handled by caller*/
1155
	}else if (size==(size_t)ret){
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
		logbuf=make_logbuf(obj, BELLE_SIP_LOG_MESSAGE, buffer,size);
		if (logbuf) {
			belle_sip_message("channel [%p]: message %s to [%s://%s:%i], size: [%i] bytes\n%s"
								,obj
								,obj->stack->send_error==0?"sent":"silently discarded"
								,belle_sip_channel_get_transport_name(obj)
								,obj->peer_name
								,obj->peer_port
								,ret
								,logbuf);
		}
1167
	}else{
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
		logbuf=make_logbuf(obj, BELLE_SIP_LOG_MESSAGE,buffer,ret);
		if (logbuf) {
			belle_sip_message("channel [%p]: message partly sent to [%s://%s:%i], sent: [%i/%i] bytes:\n%s"
								,obj
								,belle_sip_channel_get_transport_name(obj)
								,obj->peer_name
								,obj->peer_port
								,ret
								,(int)size
								,logbuf);
		}
1179
	}
1180 1181
	if (logbuf) belle_sip_free(logbuf);
	return ret;
1182 1183
}

1184 1185
static void check_content_length(belle_sip_message_t *msg, size_t body_len){
	belle_sip_header_content_length_t *ctlen=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t);
1186
	size_t value=ctlen ? belle_sip_header_content_length_get_content_length(ctlen) : 0;
1187 1188
	if (body_len){
		if (ctlen==NULL){
1189
			belle_sip_message("message [%p] has body of size ["FORMAT_SIZE_T"] but no Content-Length, adding it.",msg,body_len);
1190
			belle_sip_message_add_header(msg,
1191
				(belle_sip_header_t*)belle_sip_header_content_length_create(body_len)
1192 1193
			);
		}else{
1194
			if (value!=body_len){
1195 1196
				belle_sip_warning("message [%p] has Content-Length ["FORMAT_SIZE_T"] and body size ["FORMAT_SIZE_T"] which are inconsistent, fixing it.",
					msg, value, body_len);
1197
				belle_sip_header_content_length_set_content_length(ctlen,body_len);
1198 1199 1200 1201 1202
			}
		}
	}else{
		/*no body, or undetermined size body*/
		if (ctlen && value!=0){
1203
			belle_sip_error("message [%p] has Content-Length ["FORMAT_SIZE_T"], but without body or body with undetermined size. Fix your app.",
1204 1205 1206 1207
				msg,value);
		}
	}
}