channel.c 35.7 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

23 24
static void channel_prepare_continue(belle_sip_channel_t *obj);
static void channel_process_queue(belle_sip_channel_t *obj);
25 26
static void channel_begin_background_task(belle_sip_channel_t *obj);
static void channel_end_background_task(belle_sip_channel_t *obj);
27

Simon Morlat's avatar
Simon Morlat committed
28
const char *belle_sip_channel_state_to_string(belle_sip_channel_state_t state){
29 30 31 32 33 34 35 36 37
	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";
38 39
		case BELLE_SIP_CHANNEL_RETRY:
			return "RETRY";
40 41 42 43
		case BELLE_SIP_CHANNEL_READY:
			return "READY";
		case BELLE_SIP_CHANNEL_ERROR:
			return "ERROR";
jehan's avatar
jehan committed
44
		case BELLE_SIP_CHANNEL_DISCONNECTED:
45
			return "DISCONNECTED";
46 47
	}
	return "BAD";
48
}
49

50 51 52 53 54 55 56 57 58 59
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;
}

60
static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
61
	if (obj->peer_list) freeaddrinfo(obj->peer_list);
62
	if (obj->peer_cname) belle_sip_free(obj->peer_cname);
63
	belle_sip_free(obj->peer_name);
64
	if (obj->local_ip) belle_sip_free(obj->local_ip);
65
	obj->listeners=for_each_weak_unref_free(obj->listeners,(belle_sip_object_destroy_notify_t)belle_sip_channel_remove_listener,obj);
66
	if (obj->resolver_ctx>0) belle_sip_resolver_context_cancel(obj->resolver_ctx);
67 68 69 70
	if (obj->inactivity_timer){
		belle_sip_main_loop_remove_source(obj->stack->ml,obj->inactivity_timer);
		belle_sip_object_unref(obj->inactivity_timer);
	}
71
	if (obj->public_ip) belle_sip_free(obj->public_ip);
72 73
	channel_end_background_task(obj);/*normally this should do nothing because it sould have been terminated already,
		however leaving a background task open is so dangerous that we have to be paranoid*/
74
	belle_sip_message("Channel [%p] destroyed",obj);
75 76
}

77 78
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_channel_t);

79
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_channel_t)
80
	{
Simon Morlat's avatar
Simon Morlat committed
81
		BELLE_SIP_VPTR_INIT(belle_sip_channel_t,belle_sip_source_t,FALSE),
82 83
		(belle_sip_object_destroy_t)belle_sip_channel_destroy,
		NULL, /*clone*/
84
		NULL, /*marshal*/
85
	}
86
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
87

jehan's avatar
jehan committed
88 89 90 91
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;
Ghislain MARY's avatar
Ghislain MARY committed
92
	int err;
93 94 95
	struct sockaddr_storage saddr;
	socklen_t slen=sizeof(saddr);
	
jehan's avatar
jehan committed
96 97 98 99
	if (!origin) {
		belle_sip_warning("cannot fix via for message [%p], probably a test",msg);
		return;
	}
100 101
	belle_sip_address_remove_v4_mapping(origin->ai_addr, (struct sockaddr*)&saddr, &slen);
	err=getnameinfo((struct sockaddr*)&saddr,slen,received,sizeof(received),
jehan's avatar
jehan committed
102 103 104 105 106 107 108
	                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){
109 110 111 112 113 114 115 116 117 118
		const char* host = belle_sip_header_via_get_host(via);
		
		if (strcmp(host,received)!=0)
				belle_sip_header_via_set_received(via,received);
			
		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
119 120
	}
}
121

jehan's avatar
jehan committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
/*token       =  1*(alphanum / "-" / "." / "!" / "%" / "*"
                     / "_" / "+" / "`" / "'" / "~" )
 *
 * */
static int is_token(const char* buff,size_t bufflen ) {
	int i;
	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
153
static int get_message_start_pos(char *buff, size_t bufflen) {
Simon Morlat's avatar
Simon Morlat committed
154
	/*FIXME still to optimize and better test, specially REQUEST PATH and error path*/
jehan's avatar
jehan committed
155 156 157
	int i;
	int res=0;
	int status_code;
Simon Morlat's avatar
Simon Morlat committed
158
	char method[17]={0};
jehan's avatar
jehan committed
159
	char saved_char1;
Simon Morlat's avatar
Simon Morlat committed
160
	char sip_version[10]={0};
jehan's avatar
jehan committed
161
	int saved_char1_index;
162

163
	for(i=0; i<(int)bufflen-12;i++) { /*9=strlen( SIP/2.0\r\n)*/
jehan's avatar
jehan committed
164 165 166
		switch (buff[i]) { /*to avoid this character to be ignored by scanf*/
			case '\r':
			case '\n':
167 168
			case ' ' :
			case '\t':
jehan's avatar
jehan committed
169 170 171 172
				continue;
			default:
				break;
		}
jehan's avatar
jehan committed
173 174 175
		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
fix tag  
jehan committed
176
		res=sscanf(buff+i,"SIP/2.0 %d ",&status_code);
jehan's avatar
jehan committed
177
		if (res!=1) res=sscanf(buff+i,"HTTP/1.%*i %d ",&status_code); /*might be HTTP ?*/
jehan's avatar
fix tag  
jehan committed
178
		if (res!=1) {
179
			res= sscanf(buff+i,"%16s %*s %9s\r\n",method,sip_version)==2
jehan's avatar
jehan committed
180
					&& is_token(method,sizeof(method))
Simon Morlat's avatar
Simon Morlat committed
181
					&& (strcmp("SIP/2.0",sip_version)==0 || strncmp("HTTP/1.",sip_version,strlen("HTTP/1."))==0);
jehan's avatar
jehan committed
182
		}
jehan's avatar
fix tag  
jehan committed
183 184
		buff[saved_char1_index]=saved_char1;
		if (res==1) return i;
jehan's avatar
jehan committed
185
	}
jehan's avatar
jehan committed
186 187 188
	return -1;
}

189
static void belle_sip_channel_input_stream_reset(belle_sip_channel_input_stream_t* input_stream) {
190 191 192 193 194 195 196 197
	int remaining;
	
	remaining=input_stream->write_ptr-input_stream->read_ptr;
	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;
198
		*input_stream->write_ptr='\0';
199 200 201
	}else{
		input_stream->read_ptr=input_stream->write_ptr=input_stream->buff;
	}
jehan's avatar
jehan committed
202 203
	input_stream->state=WAITING_MESSAGE_START;
	input_stream->msg=NULL;
204 205 206 207 208 209
	input_stream->chuncked_mode=FALSE;
	input_stream->content_length=-1;
	if (input_stream->body){
		belle_sip_free(input_stream->body);
		input_stream->body=NULL;
	}
jehan's avatar
jehan committed
210
}
211

212
static size_t belle_sip_channel_input_stream_get_buff_length(belle_sip_channel_input_stream_t* input_stream) {
jehan's avatar
jehan committed
213
	return MAX_CHANNEL_BUFF_SIZE - (input_stream->write_ptr-input_stream->buff);
jehan's avatar
jehan committed
214 215
}

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
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;
		
		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;
	
	if (!via){
		belle_sip_error("channel [%p]: no via in response.",obj);
		return;
	}
250 251 252 253 254

	if (!(received=belle_sip_header_via_get_received(via))) {
		/*use address from via*/;
		received=belle_sip_header_via_get_host(via);
	}
255
	
256 257 258 259
	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);
260
	}
261 262
	belle_sip_channel_set_public_ip_port(obj,received,rport);

263
	obj->learnt_ip_port=TRUE;
264 265
}

266
static void belle_sip_channel_message_ready(belle_sip_channel_t *obj){
267 268 269
	belle_sip_message_t *msg=obj->input_stream.msg;
	if (belle_sip_message_is_response(msg)) belle_sip_channel_learn_public_ip_port(obj,BELLE_SIP_RESPONSE(msg));
	obj->incoming_messages=belle_sip_list_append(obj->incoming_messages,msg);
270
	belle_sip_channel_input_stream_reset(&obj->input_stream);
271 272
}

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
/*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);
	obj->input_stream.content_length= content_length_header ? belle_sip_header_content_length_get_content_length(content_length_header) : 0;
	
	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_sip_response_t) || BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_sip_request_t)){
		return obj->input_stream.content_length>0;
	}else{/*http*/
		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");
			
			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;
				}
			}
			return TRUE;
		}
295 296 297 298
	}
	return FALSE;
}

299 300
static int acquire_body_simple(belle_sip_channel_t *obj, int end_of_stream){
	int content_length=obj->input_stream.content_length;
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
	
	if (end_of_stream && content_length==-1){
		content_length=obj->input_stream.write_ptr-obj->input_stream.read_ptr;
	}
	if (content_length!=-1 && content_length <= obj->input_stream.write_ptr-obj->input_stream.read_ptr){
		/*great body completed
		belle_sip_message("channel [%p] read [%i] bytes of body from %s:%i\n%s"	,obj
			,content_length
			,obj->peer_name
			,obj->peer_port
			,obj->input_stream.read_ptr);*/
		belle_sip_message_set_body(obj->input_stream.msg,obj->input_stream.read_ptr,content_length);
		obj->input_stream.read_ptr+=content_length;
		belle_sip_channel_message_ready(obj);
		return BELLE_SIP_CONTINUE;
	}else{
		/*body is not finished, we need more data*/
		return BELLE_SIP_STOP;
	}
}

322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
static int acquire_chuncked_body(belle_sip_channel_t *obj, int end_of_stream){
	belle_sip_channel_input_stream_t *st=&obj->input_stream;
	do{
		if (st->chunk_size==-1){
			char *tmp;
			belle_sip_message("seeing: %s",st->read_ptr);
			while ( (tmp=strstr(st->read_ptr,"\r\n"))==st->read_ptr){/*skip \r\n*/
				st->read_ptr+=2;
			}
			
			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");
						belle_sip_message_assign_body(obj->input_stream.msg,(char*)st->body,st->content_length);
						st->body=NULL;
						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{
						belle_sip_message("Getting chunk of %i bytes",(int)chunksize);
						st->chunk_size=chunksize;
						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;
			}
		}
		if (st->chunk_size<=st->write_ptr-st->read_ptr){
			/*we have a chunk completed*/
			int prev_ctlen=st->content_length;
			st->content_length+=st->chunk_size;
			st->body=belle_sip_realloc(st->body,st->content_length);
			memcpy(st->body+prev_ctlen,st->read_ptr,st->chunk_size);
			st->read_ptr+=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;
		}
	}while(1);
}

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

381
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj, int end_of_stream){
jehan's avatar
jehan committed
382
	int offset;
383
	size_t read_size=0;
384 385 386 387
	int num;
	
	while ((num=(obj->input_stream.write_ptr-obj->input_stream.read_ptr))>0){
	
jehan's avatar
jehan committed
388
		if (obj->input_stream.state == WAITING_MESSAGE_START) {
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
			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
409
				}
410 411 412 413 414
			}

			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
415 416 417 418 419
			}
		}

		if (obj->input_stream.state==MESSAGE_AQUISITION) {
			/*search for \r\n\r\n*/
jehan's avatar
jehan committed
420 421
			char* end_of_message=NULL;
			if ((end_of_message=strstr(obj->input_stream.read_ptr,"\r\n\r\n"))){
422 423
				int bytes_to_parse;
				char tmp;
424
				/*end of message found*/
jehan's avatar
jehan committed
425
				end_of_message+=4;/*add \r\n\r\n*/
426 427 428
				bytes_to_parse=end_of_message-obj->input_stream.read_ptr;
				tmp=*end_of_message;
				*end_of_message='\0';/*this is in order for the following log to print the message only to its end.*/
429
				/*belle_sip_message("channel [%p] read message of [%i] bytes:\n%.40s...",obj, bytes_to_parse, obj->input_stream.read_ptr);*/
430
				obj->input_stream.msg=belle_sip_message_parse_raw(obj->input_stream.read_ptr
431
										,bytes_to_parse
432
										,&read_size);
433
				*end_of_message=tmp;
434 435
				obj->input_stream.read_ptr+=read_size;
				if (obj->input_stream.msg && read_size > 0){
436
					belle_sip_message("channel [%p] [%i] bytes parsed",obj,(int)read_size);
437 438 439
					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*/
440
					
441
					if (check_body(obj)){
442 443 444 445 446
						obj->input_stream.state=BODY_AQUISITION;
					} else {
						/*no body*/
						belle_sip_channel_message_ready(obj);
						continue;
jehan's avatar
jehan committed
447
					}
448
				}else{
jehan's avatar
jehan committed
449 450 451 452 453
					belle_sip_error("Could not parse [%s], on channel [%p] skipping to [%s]",obj->input_stream.read_ptr
																							,obj
																							,end_of_message);
					obj->input_stream.read_ptr=end_of_message;
					obj->input_stream.state=WAITING_MESSAGE_START;
454
					continue;
jehan's avatar
jehan committed
455
				}
456
			}else break; /*The message isn't finished to be receive, we need more data*/
jehan's avatar
jehan committed
457 458 459
		}

		if (obj->input_stream.state==BODY_AQUISITION) {
460
			if (acquire_body(obj,end_of_stream)==BELLE_SIP_STOP) break;
jehan's avatar
jehan committed
461
		}
462
	}
463 464
	if (obj->incoming_messages)
		BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_event,obj,BELLE_SIP_EVENT_READ/*always a read event*/);
465 466 467 468 469 470 471 472
}

int belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents){
	int num;

	if (revents & BELLE_SIP_EVENT_READ) {
		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);
473
		} else {
474 475
			belle_sip_message("channel [%p]: simulating recv() returning %i",obj,obj->simulated_recv_return);
			num=obj->simulated_recv_return;
Simon Morlat's avatar
Simon Morlat committed
476
		}
477 478 479 480 481
	} else {
		belle_sip_error("Unexpected event [%i] on channel [%p]",revents,obj);
		num=-1; /*to trigger an error*/
	}
	if (num>0){
482
		char *begin=obj->input_stream.write_ptr;
483 484 485
		obj->input_stream.write_ptr+=num;
		/*first null terminate the read buff*/
		*obj->input_stream.write_ptr='\0';
Simon Morlat's avatar
Simon Morlat committed
486
		if (num>50) /*to avoid tracing server based keep alives*/
487 488 489 490 491 492 493
			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,
					begin);
494
		belle_sip_channel_parse_stream(obj,FALSE);
jehan's avatar
jehan committed
495
	} else if (num == 0) {
496 497
		/*before closing the channel, check if there was a pending message to receive, whose body acquisition is to be finished.*/
		belle_sip_channel_parse_stream(obj,TRUE);
jehan's avatar
jehan committed
498
		channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
jehan's avatar
jehan committed
499
		return BELLE_SIP_STOP;
500 501 502 503
	} else if ( belle_sip_error_code_is_would_block(-num)){
		belle_sip_message("EWOULDBLOCK");
		return BELLE_SIP_CONTINUE;
	}else{
jehan's avatar
jehan committed
504
		belle_sip_error("Receive error on channel [%p]",obj);
jehan's avatar
jehan committed
505
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
jehan's avatar
jehan committed
506
		return BELLE_SIP_STOP;
jehan's avatar
jehan committed
507
	}
jehan's avatar
jehan committed
508
	return BELLE_SIP_CONTINUE;
Simon Morlat's avatar
Simon Morlat committed
509
}
510

511 512
static int channel_inactive_timeout(void *data, unsigned int event){
	belle_sip_channel_t *obj=(belle_sip_channel_t *)data;
513
	belle_sip_message("Channel [%p]: inactivity timeout reached.",obj);
514 515 516 517
	channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
	return BELLE_SIP_STOP;
}

518
static void update_inactivity_timer(belle_sip_channel_t *obj, int from_recv){
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
	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;
		}
	}
534 535
	if (from_recv)
		obj->last_recv_time=belle_sip_time_ms();
536
}
jehan's avatar
jehan committed
537

Simon Morlat's avatar
Simon Morlat committed
538 539 540 541 542 543 544
/*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.
 */
545
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){
546 547 548 549
	/*to initialize our base class:*/
	belle_sip_channel_set_socket(obj,-1,NULL);
	
	/*then initialize members*/
Simon Morlat's avatar
Simon Morlat committed
550
	obj->ai_family=AF_INET;
551
	obj->peer_cname=peer_cname ? belle_sip_strdup(peer_cname) : NULL;
552 553
	obj->peer_name=belle_sip_strdup(peername);
	obj->peer_port=peer_port;
554
	obj->stack=stack;
Simon Morlat's avatar
Simon Morlat committed
555 556 557 558 559 560
	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;
	}
561
	obj->local_port=localport;
Simon Morlat's avatar
Simon Morlat committed
562
	obj->simulated_recv_return=1;/*not set*/
563 564 565 566 567 568
	if (peername){
		/*check if we are given a real dns name or just an ip address*/
		struct addrinfo *ai=belle_sip_ip_address_to_addrinfo(AF_UNSPEC,peername,peer_port);
		if (ai) freeaddrinfo(ai);
		else obj->has_name=TRUE;
	}
569
	belle_sip_channel_input_stream_reset(&obj->input_stream);
570
	update_inactivity_timer(obj,FALSE);
571 572
}

Simon Morlat's avatar
Simon Morlat committed
573
/*constructor for channels created by incoming connections*/
574 575 576 577 578 579 580 581 582 583
void belle_sip_channel_init_with_addr(belle_sip_channel_t *obj, belle_sip_stack_t *stack, const struct sockaddr *peer_addr, socklen_t addrlen){
	char remoteip[64];
	struct addrinfo ai;
	int peer_port;
	
	memset(&ai,0,sizeof(ai));
	ai.ai_family=peer_addr->sa_family;
	ai.ai_addr=(struct sockaddr*)peer_addr;
	ai.ai_addrlen=addrlen;
	belle_sip_addrinfo_to_ip(&ai,remoteip,sizeof(remoteip),&peer_port);
584
	belle_sip_channel_init(obj,stack,NULL,0,NULL,remoteip,peer_port);
585
	obj->peer_list=obj->current_peer=belle_sip_ip_address_to_addrinfo(ai.ai_family, obj->peer_name,obj->peer_port);
Simon Morlat's avatar
Simon Morlat committed
586
	obj->ai_family=ai.ai_family;
587 588
}

Simon Morlat's avatar
Simon Morlat committed
589
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
590 591 592 593 594 595
	belle_sip_socket_source_init((belle_sip_source_t*)obj
									, datafunc
									, obj
									, sock
									, BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_WRITE
									, -1);
596 597
}

598 599 600 601 602 603 604 605 606 607 608
void belle_sip_channel_add_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
	obj->listeners=belle_sip_list_append(obj->listeners,
	                belle_sip_object_weak_ref(l,
	                (belle_sip_object_destroy_notify_t)belle_sip_channel_remove_listener,obj));
}

void belle_sip_channel_remove_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
	belle_sip_object_weak_unref(l,(belle_sip_object_destroy_notify_t)belle_sip_channel_remove_listener,obj);
	obj->listeners=belle_sip_list_remove(obj->listeners,l);
}

609 610 611 612
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const belle_sip_hop_t *hop, const struct addrinfo *addr){
	if (hop && strcmp(hop->host,obj->peer_name)==0 && hop->port==obj->peer_port){
		if (hop->cname && obj->peer_cname && strcmp(hop->cname,obj->peer_cname)!=0)
			return 0; /*cname mismatch*/
613
		return 1;
614
	}
615
	if (addr && obj->current_peer)
616
		return addr->ai_addrlen==obj->current_peer->ai_addrlen && memcmp(addr->ai_addr,obj->current_peer->ai_addr,addr->ai_addrlen)==0;
617 618 619
	return 0;
}

620 621 622 623 624
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;
}

625 626 627
int belle_sip_channel_is_reliable(const belle_sip_channel_t *obj){
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->reliable;
}
628

jehan's avatar
jehan committed
629 630 631 632 633 634 635 636 637 638 639
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;
	}
}
640

641
const char * belle_sip_channel_get_transport_name(const belle_sip_channel_t *obj){
642
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->transport;
643 644 645
}

int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
646
	update_inactivity_timer(obj,FALSE);
647 648 649 650
	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){
651
	update_inactivity_timer(obj,TRUE);
652 653 654
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->channel_recv(obj,buf,buflen);
}

655
void belle_sip_channel_close(belle_sip_channel_t *obj){
656
	if (BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->close)
657
		BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->close(obj); /*udp channel doesn't have close function*/
658 659
	belle_sip_main_loop_remove_source(obj->stack->ml,(belle_sip_source_t*)obj);
	belle_sip_source_uninit((belle_sip_source_t*)obj);
660 661
}

662
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
663
	return obj->current_peer;
664 665
}

666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
static void channel_on_background_task_ended(belle_sip_channel_t *obj){
	belle_sip_warning("channel [%p]: background task has to be ended now, but work isn't finished.",obj);
	channel_end_background_task(obj);
}

static void channel_begin_background_task(belle_sip_channel_t *obj){
	if (obj->bg_task_id==0){
		obj->bg_task_id=belle_sip_begin_background_task("belle-sip channel in progress",(void (*)(void*))channel_on_background_task_ended, obj);
		if (obj->bg_task_id) belle_sip_message("channel [%p]: starting background task with id=[%x].",obj,obj->bg_task_id);
	}else belle_sip_warning("channel [%p]: already a background task pending.",obj);
}


static void channel_end_background_task(belle_sip_channel_t *obj){
	if (obj->bg_task_id){
		belle_sip_message("channel [%p]: ending background task with id=[%x].",obj,obj->bg_task_id);
		belle_sip_end_background_task(obj->bg_task_id);
		obj->bg_task_id=0;
	}
}

jehan's avatar
jehan committed
687
belle_sip_message_t* belle_sip_channel_pick_message(belle_sip_channel_t *obj) {
jehan's avatar
jehan committed
688 689
	belle_sip_message_t* result=NULL;
	belle_sip_list_t* front;
690
	if ((front=obj->incoming_messages)!=NULL) {
jehan's avatar
jehan committed
691 692 693 694
		result = (belle_sip_message_t*)obj->incoming_messages->data;
		obj->incoming_messages=belle_sip_list_remove_link(obj->incoming_messages,obj->incoming_messages);
		belle_sip_free(front);
	}
jehan's avatar
jehan committed
695 696
	return result;
}
697

Simon Morlat's avatar
Simon Morlat committed
698
static void channel_invoke_state_listener(belle_sip_channel_t *obj){
699 700 701
	if (obj->state==BELLE_SIP_CHANNEL_DISCONNECTED || obj->state==BELLE_SIP_CHANNEL_ERROR){
		belle_sip_channel_close(obj);
	}
Simon Morlat's avatar
Simon Morlat committed
702
	BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_state_changed,obj,obj->state);
Simon Morlat's avatar
Simon Morlat committed
703 704
}

705 706 707 708 709
static void channel_invoke_state_listener_defered(belle_sip_channel_t *obj){
	channel_invoke_state_listener(obj);
	belle_sip_object_unref(obj);
}

710 711 712 713 714
static void channel_connect_next(belle_sip_channel_t *obj){
	belle_sip_channel_connect(obj);
	belle_sip_object_unref(obj);
}

715
static void belle_sip_channel_handle_error(belle_sip_channel_t *obj){
716 717 718 719 720 721 722
	if (obj->state!=BELLE_SIP_CHANNEL_READY){
		/* Previous connection attempts were failed (channel could not get ready).*/
		/* 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);
723
			belle_sip_main_loop_do_later(obj->stack->ml,(belle_sip_callback_t)channel_connect_next,belle_sip_object_ref(obj));
724 725 726
			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*/
727 728
	
	obj->state=BELLE_SIP_CHANNEL_ERROR;
729
	channel_end_background_task(obj);
730
	/*Because error notification will in practice trigger the destruction of possible transactions and this channel,
731 732 733
	* 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.
	*/
734
	belle_sip_main_loop_do_later(obj->stack->ml,(belle_sip_callback_t)channel_invoke_state_listener_defered,belle_sip_object_ref(obj));
735 736
}

737 738 739 740 741 742 743 744
int belle_sip_channel_notify_timeout(belle_sip_channel_t *obj){
	const int too_long=60;
	if (belle_sip_time_ms() - obj->last_recv_time>=(too_long * 1000)){
		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
745 746
}

747 748 749 750 751 752 753
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));
	
	if (state==BELLE_SIP_CHANNEL_ERROR){
		belle_sip_channel_handle_error(obj);
	}else{
		obj->state=state;
754 755 756
		if (state==BELLE_SIP_CHANNEL_DISCONNECTED){
			channel_end_background_task(obj);
		}
Simon Morlat's avatar
Simon Morlat committed
757
		channel_invoke_state_listener(obj);
758
	}
759
}
760

Simon Morlat's avatar
Simon Morlat committed
761
static void _send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
762
	char buffer[belle_sip_network_buffer_size];
763
	size_t len=0;
764
	int ret=0;
Ghislain MARY's avatar
Ghislain MARY committed
765
	belle_sip_error_code error=BELLE_SIP_OK;
Simon Morlat's avatar
Simon Morlat committed
766
	
767
	BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_sending,obj,msg);
Ghislain MARY's avatar
Ghislain MARY committed
768 769
	error=belle_sip_object_marshal((belle_sip_object_t*)msg,buffer,sizeof(buffer),&len);
	if ((error==BELLE_SIP_OK) && (len>0)){
770
		buffer[len]='\0';
771 772 773 774 775 776 777 778
		if (!obj->stack->send_error)
			ret=belle_sip_channel_send(obj,buffer,len);
		else
			/*debug case*/
			ret=obj->stack->send_error;

		if (ret<0){
			belle_sip_error("channel [%p]: could not send [%i] bytes from [%s://%s:%i]  to [%s:%i]"	,obj
Simon Morlat's avatar
Simon Morlat committed
779
				,(int)len
Simon Morlat's avatar
Simon Morlat committed
780 781 782 783 784
				,belle_sip_channel_get_transport_name(obj)
				,obj->local_ip
				,obj->local_port
				,obj->peer_name
				,obj->peer_port);
785
			channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
Simon Morlat's avatar
Simon Morlat committed
786 787 788 789 790 791 792 793
		}else if (len==ret){
			belle_sip_message("channel [%p]: message sent to [%s://%s:%i], size: [%i] bytes\n%s"
								,obj
								,belle_sip_channel_get_transport_name(obj)
								,obj->peer_name
								,obj->peer_port
								,ret
								,buffer);
794
		}else{
Simon Morlat's avatar
Simon Morlat committed
795
			belle_sip_error("channel [%p]: message partly sent to [%s://%s:%i], sent: [%i/%i] bytes:\n%s"
jehan's avatar
jehan committed
796 797 798 799
								,obj
								,belle_sip_channel_get_transport_name(obj)
								,obj->peer_name
								,obj->peer_port
Simon Morlat's avatar
Simon Morlat committed
800
								,ret
Simon Morlat's avatar
Simon Morlat committed
801
								,(int)len
jehan's avatar
jehan committed
802
								,buffer);
803 804 805 806
		}
	}
}

Simon Morlat's avatar
Simon Morlat committed
807 808 809 810 811 812 813 814
/* just to emulate network transmission delay */

typedef struct delayed_send{
	belle_sip_channel_t *chan;
	belle_sip_message_t *msg;
}delayed_send_t;

static int on_delayed_send_do(delayed_send_t *ds){
815
	belle_sip_message("on_delayed_send_do(): sending now");
Simon Morlat's avatar
Simon Morlat committed
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
	if (ds->chan->state==BELLE_SIP_CHANNEL_READY){
		_send_message(ds->chan,ds->msg);
	}
	belle_sip_object_unref(ds->chan);
	belle_sip_object_unref(ds->msg);
	belle_sip_free(ds);
	return FALSE;
}

static void send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
	if (obj->stack->tx_delay>0){
		delayed_send_t *ds=belle_sip_new(delayed_send_t);
		ds->chan=(belle_sip_channel_t*)belle_sip_object_ref(obj);
		ds->msg=(belle_sip_message_t*)belle_sip_object_ref(msg);
		belle_sip_main_loop_add_timeout(obj->stack->ml,(belle_sip_source_func_t)on_delayed_send_do,ds,obj->stack->tx_delay);
831
		belle_sip_message("channel %p: message sending delayed by %i ms",obj,obj->stack->tx_delay);
Simon Morlat's avatar
Simon Morlat committed
832 833
	}else _send_message(obj,msg);
}
834

Simon Morlat's avatar
Simon Morlat committed
835
void belle_sip_channel_prepare(belle_sip_channel_t *obj){
836
	channel_prepare_continue(obj);
Simon Morlat's avatar
Simon Morlat committed
837 838
}

839 840 841 842 843 844 845 846 847 848 849 850 851 852
static void channel_push_outgoing(belle_sip_channel_t *obj, belle_sip_message_t *msg){
	obj->outgoing_messages=belle_sip_list_append(obj->outgoing_messages,msg);
}

static belle_sip_message_t *channel_pop_outgoing(belle_sip_channel_t *obj){
	belle_sip_message_t *msg=NULL;
	if (obj->outgoing_messages){
		msg=(belle_sip_message_t*)obj->outgoing_messages->data;
		obj->outgoing_messages=belle_sip_list_delete_link(obj->outgoing_messages,obj->outgoing_messages);
	}
	return msg;
}

static void channel_prepare_continue(belle_sip_channel_t *obj){
Simon Morlat's avatar
Simon Morlat committed
853 854
	switch(obj->state){
		case BELLE_SIP_CHANNEL_INIT:
855
			channel_begin_background_task(obj);
856
			belle_sip_channel_resolve(obj);
Simon Morlat's avatar
Simon Morlat committed
857 858
		break;
		case BELLE_SIP_CHANNEL_RES_DONE:
859
			belle_sip_channel_connect(obj);
Simon Morlat's avatar
Simon Morlat committed
860 861
		break;
		case BELLE_SIP_CHANNEL_READY:
862
			channel_process_queue(obj);
Simon Morlat's avatar
Simon Morlat committed
863 864 865
		break;
		default:
		break;
866
	}
867 868 869 870 871 872
}

static void channel_process_queue(belle_sip_channel_t *obj){
	belle_sip_message_t *msg;
	belle_sip_object_ref(obj);/* we need to ref ourself because code below may trigger our destruction*/

873
	while((msg=channel_pop_outgoing(obj))!=NULL && obj->state==BELLE_SIP_CHANNEL_READY) {
874 875 876 877
		send_message(obj, msg);
		belle_sip_object_unref(msg);
	}

Simon Morlat's avatar
Simon Morlat committed
878
	belle_sip_object_unref(obj);
879 880
}

jehan's avatar
jehan committed
881
void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t slen){
882 883 884 885
	char name[NI_MAXHOST];
	char serv[NI_MAXSERV];

	if (obj->local_ip==NULL){
886 887
		struct sockaddr_storage saddr;
		socklen_t slen2=sizeof(saddr);
888
		int err;
889 890 891
		
		belle_sip_address_remove_v4_mapping(addr,(struct sockaddr*) &saddr,&slen2);
		
892
		err=getnameinfo((struct sockaddr*)&saddr,slen,name,sizeof(name),serv,sizeof(serv),NI_NUMERICHOST|NI_NUMERICSERV);
893
		if (err!=0){
894
			belle_sip_error("belle_sip_channel_set_ready(): getnameinfo() failed: %s",gai_strerror(err));
895 896 897 898 899 900 901 902
		}else{
			obj->local_ip=belle_sip_strdup(name);
			obj->local_port=atoi(serv);
			belle_sip_message("Channel has local address %s:%s",name,serv);
		}
	}
	channel_set_state(obj,BELLE_SIP_CHANNEL_READY);
	channel_process_queue(obj);
903
	channel_end_background_task(obj);
904 905
}

906
static void channel_res_done(void *data, const char *name, struct addrinfo *ai_list){
907
	belle_sip_channel_t *obj=(belle_sip_channel_t*)data;
908 909 910 911
	if (obj->resolver_ctx){
		belle_sip_object_unref(obj->resolver_ctx);
		obj->resolver_ctx=NULL;
	}
912 913
	if (ai_list){
		obj->peer_list=obj->current_peer=ai_list;
914
		channel_set_state(obj,BELLE_SIP_CHANNEL_RES_DONE);
915
		channel_prepare_continue(obj);
916
	}else{
917
		belle_sip_error("%s: DNS resolution failed", __FUNCTION__);
918
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
919 920 921
	}
}

jehan's avatar
jehan committed
922
void belle_sip_channel_resolve(belle_sip_channel_t *obj){
923
	channel_set_state(obj,BELLE_SIP_CHANNEL_RES_IN_PROGRESS);
Simon Morlat's avatar
Simon Morlat committed
924 925
	if (belle_sip_stack_dns_srv_enabled(obj->stack) && obj->lp!=NULL)
		obj->resolver_ctx=belle_sip_stack_resolve(obj->stack, belle_sip_channel_get_transport_name_lower_case(obj), obj->peer_name, obj->peer_port, obj->ai_family, channel_res_done, obj);
926
	else
Simon Morlat's avatar
Simon Morlat committed
927
		obj->resolver_ctx=belle_sip_stack_resolve_a(obj->stack, obj->peer_name, obj->peer_port, obj->ai_family, channel_res_done, obj);
928 929
	if (obj->resolver_ctx){
		belle_sip_object_ref(obj->resolver_ctx);
930
	}
jehan's avatar
jehan committed
931
	return ;
932 933
}

jehan's avatar
jehan committed
934
void belle_sip_channel_connect(belle_sip_channel_t *obj){
935 936
	char ip[64];
	
jehan's avatar
jehan committed
937
	channel_set_state(obj,BELLE_SIP_CHANNEL_CONNECTING);
938 939 940 941
	belle_sip_addrinfo_to_ip(obj->current_peer,ip,sizeof(ip),NULL);
	belle_sip_message("Trying to connect to [%s://%s:%i]",belle_sip_channel_get_transport_name(obj),ip,obj->peer_port);
	
	if(BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->connect(obj,obj->current_peer)) {
Simon Morlat's avatar
Simon Morlat committed
942
		belle_sip_error("Cannot connect to [%s://%s:%i]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port);
jehan's avatar
jehan committed
943 944 945
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
	}
	return;
946 947 948
}

int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
949 950 951
	belle_sip_object_ref(msg);
	channel_push_outgoing(obj,msg);
	if (obj->state==BELLE_SIP_CHANNEL_INIT){
Simon Morlat's avatar
Simon Morlat committed
952
		belle_sip_channel_prepare(obj);
953 954 955
	}else if (obj->state==BELLE_SIP_CHANNEL_READY) {
		channel_process_queue(obj);
	}		
956 957 958
	return 0;
}

Simon Morlat's avatar
Simon Morlat committed
959 960 961 962
void belle_sip_channel_force_close(belle_sip_channel_t *obj){
	obj->force_close=1;
	channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
}
963

Simon Morlat's avatar
Simon Morlat committed
964 965 966 967 968 969
belle_sip_channel_t *