channel.c 28.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
	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
    the Free Software Foundation, either version 3 of the License, or
    (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"

22 23 24
static void channel_prepare_continue(belle_sip_channel_t *obj);
static void channel_process_queue(belle_sip_channel_t *obj);

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

47 48 49 50 51 52 53 54 55 56
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;
}

57
static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
58
	if (obj->peer_list) freeaddrinfo(obj->peer_list);
59
	if (obj->peer_cname) belle_sip_free(obj->peer_cname);
60
	belle_sip_free(obj->peer_name);
61
	if (obj->local_ip) belle_sip_free(obj->local_ip);
62
	obj->listeners=for_each_weak_unref_free(obj->listeners,(belle_sip_object_destroy_notify_t)belle_sip_channel_remove_listener,obj);
63
	if (obj->resolver_ctx>0) belle_sip_resolver_context_cancel(obj->resolver_ctx);
64 65 66 67
	if (obj->inactivity_timer){
		belle_sip_main_loop_remove_source(obj->stack->ml,obj->inactivity_timer);
		belle_sip_object_unref(obj->inactivity_timer);
	}
68
	if (obj->public_ip) belle_sip_free(obj->public_ip);
69
	belle_sip_message("Channel [%p] destroyed",obj);
70 71
}

72 73
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_channel_t);

74
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_channel_t)
75
	{
Simon Morlat's avatar
Simon Morlat committed
76
		BELLE_SIP_VPTR_INIT(belle_sip_channel_t,belle_sip_source_t,FALSE),
77 78
		(belle_sip_object_destroy_t)belle_sip_channel_destroy,
		NULL, /*clone*/
79
		NULL, /*marshal*/
80
	}
81
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
82

jehan's avatar
jehan committed
83 84 85 86
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
87
	int err;
jehan's avatar
jehan committed
88 89 90 91
	if (!origin) {
		belle_sip_warning("cannot fix via for message [%p], probably a test",msg);
		return;
	}
Ghislain MARY's avatar
Ghislain MARY committed
92
	err=getnameinfo(origin->ai_addr,origin->ai_addrlen,received,sizeof(received),
jehan's avatar
jehan committed
93 94 95 96 97 98 99
	                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){
100 101 102 103 104 105 106 107 108 109
		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
110 111
	}
}
112

jehan's avatar
jehan committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
/*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
144 145 146 147 148
static int get_message_start_pos(char *buff, size_t bufflen) {
	/*FIXME still to optimize an better tested, specially REQUEST PATH and error path*/
	int i;
	int res=0;
	int status_code;
149
	char method[17];
jehan's avatar
jehan committed
150
	char saved_char1;
151
	char sip_version[10];
jehan's avatar
jehan committed
152
	int saved_char1_index;
153

154
	for(i=0; i<(int)bufflen-12;i++) { /*9=strlen( SIP/2.0\r\n)*/
jehan's avatar
jehan committed
155 156 157 158 159 160 161
		switch (buff[i]) { /*to avoid this character to be ignored by scanf*/
			case '\r':
			case '\n':
				continue;
			default:
				break;
		}
jehan's avatar
jehan committed
162 163 164
		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
165 166
		res=sscanf(buff+i,"SIP/2.0 %d ",&status_code);
		if (res!=1) {
167
			res= sscanf(buff+i,"%16s %*s %9s\r\n",method,sip_version)==2
jehan's avatar
jehan committed
168
					&& is_token(method,sizeof(method))
jehan's avatar
jehan committed
169
					&& strcmp("SIP/2.0",sip_version)==0 ;
jehan's avatar
jehan committed
170
		}
jehan's avatar
fix tag  
jehan committed
171 172
		buff[saved_char1_index]=saved_char1;
		if (res==1) return i;
jehan's avatar
jehan committed
173
	}
jehan's avatar
jehan committed
174 175 176
	return -1;
}

177
static void belle_sip_channel_input_stream_reset(belle_sip_channel_input_stream_t* input_stream) {
178 179 180 181 182 183 184 185
	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;
186
		*input_stream->write_ptr='\0';
187 188 189
	}else{
		input_stream->read_ptr=input_stream->write_ptr=input_stream->buff;
	}
jehan's avatar
jehan committed
190 191 192
	input_stream->state=WAITING_MESSAGE_START;
	input_stream->msg=NULL;
}
193

194
static size_t belle_sip_channel_input_stream_get_buff_length(belle_sip_channel_input_stream_t* input_stream) {
jehan's avatar
jehan committed
195
	return MAX_CHANNEL_BUFF_SIZE - (input_stream->write_ptr-input_stream->buff);
jehan's avatar
jehan committed
196 197
}

198 199 200 201 202 203 204 205 206 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
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;
	}
232 233 234 235 236

	if (!(received=belle_sip_header_via_get_received(via))) {
		/*use address from via*/;
		received=belle_sip_header_via_get_host(via);
	}
237
	
238 239 240 241
	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);
242
	}
243 244
	belle_sip_channel_set_public_ip_port(obj,received,rport);

245
	obj->learnt_ip_port=TRUE;
246 247
}

248
static void belle_sip_channel_message_ready(belle_sip_channel_t *obj){
249 250 251
	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);
252
	belle_sip_channel_input_stream_reset(&obj->input_stream);
253 254
}

jehan's avatar
jehan committed
255
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj){
jehan's avatar
jehan committed
256
	int offset;
257
	size_t read_size=0;
jehan's avatar
jehan committed
258 259
	belle_sip_header_content_length_t* content_length_header;
	int content_length;
260 261 262 263
	int num;
	
	while ((num=(obj->input_stream.write_ptr-obj->input_stream.read_ptr))>0){
	
jehan's avatar
jehan committed
264 265 266 267 268
		if (obj->input_stream.state == WAITING_MESSAGE_START) {
			/*search for request*/
			if ((offset=get_message_start_pos(obj->input_stream.read_ptr,num)) >=0 ) {
				/*message found !*/
				if (offset>0) {
269
					belle_sip_warning("trashing [%i] bytes in front of sip message on channel [%p]",offset,obj);
jehan's avatar
jehan committed
270 271 272 273
					obj->input_stream.read_ptr+=offset;
				}
				obj->input_stream.state=MESSAGE_AQUISITION;
			} else {
274
				belle_sip_debug("Unexpected [%s] received on channel [%p], trashing",obj->input_stream.read_ptr,obj);
275
				obj->input_stream.read_ptr=obj->input_stream.write_ptr;
276
				belle_sip_channel_input_stream_reset(&obj->input_stream);
277
				continue;
jehan's avatar
jehan committed
278 279 280 281 282
			}
		}

		if (obj->input_stream.state==MESSAGE_AQUISITION) {
			/*search for \r\n\r\n*/
jehan's avatar
jehan committed
283 284
			char* end_of_message=NULL;
			if ((end_of_message=strstr(obj->input_stream.read_ptr,"\r\n\r\n"))){
285 286
				int bytes_to_parse;
				char tmp;
287
				/*end of message found*/
jehan's avatar
jehan committed
288
				end_of_message+=4;/*add \r\n\r\n*/
289 290 291
				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.*/
292
				/*belle_sip_message("channel [%p] read message of [%i] bytes:\n%.40s...",obj, bytes_to_parse, obj->input_stream.read_ptr);*/
293
				obj->input_stream.msg=belle_sip_message_parse_raw(obj->input_stream.read_ptr
294
										,bytes_to_parse
295
										,&read_size);
296
				*end_of_message=tmp;
297 298
				obj->input_stream.read_ptr+=read_size;
				if (obj->input_stream.msg && read_size > 0){
299
					belle_sip_message("channel [%p] [%i] bytes parsed",obj,(int)read_size);
300 301 302 303 304 305 306 307 308 309 310
					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*/
					if ((content_length_header = (belle_sip_header_content_length_t*)belle_sip_message_get_header(obj->input_stream.msg,BELLE_SIP_CONTENT_LENGTH)) != NULL
							&& belle_sip_header_content_length_get_content_length(content_length_header)>0) {

						obj->input_stream.state=BODY_AQUISITION;
					} else {
						/*no body*/
						belle_sip_channel_message_ready(obj);
						continue;
jehan's avatar
jehan committed
311
					}
312
				}else{
jehan's avatar
jehan committed
313 314 315 316 317
					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;
318
					continue;
jehan's avatar
jehan committed
319
				}
320
			}else break; /*The message isn't finished to be receive, we need more data*/
jehan's avatar
jehan committed
321 322 323 324
		}

		if (obj->input_stream.state==BODY_AQUISITION) {
			content_length=belle_sip_header_content_length_get_content_length((belle_sip_header_content_length_t*)belle_sip_message_get_header(obj->input_stream.msg,BELLE_SIP_CONTENT_LENGTH));
jehan's avatar
jehan committed
325
			if (content_length <= obj->input_stream.write_ptr-obj->input_stream.read_ptr) {
326
				/*great body completed
327
				belle_sip_message("channel [%p] read [%i] bytes of body from %s:%i\n%s"	,obj
328 329 330
					,content_length
					,obj->peer_name
					,obj->peer_port
331
					,obj->input_stream.read_ptr);*/
jehan's avatar
jehan committed
332
				belle_sip_message_set_body(obj->input_stream.msg,obj->input_stream.read_ptr,content_length);
333
				obj->input_stream.read_ptr+=content_length;
334 335 336 337
				belle_sip_channel_message_ready(obj);
			}else{
				/*body is not finished, we need more data*/
				break;
jehan's avatar
jehan committed
338 339
			}
		}
340 341 342 343 344 345 346 347 348
	}
}

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);
349
		} else {
350 351
			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
352
		}
353 354 355 356 357
	} else {
		belle_sip_error("Unexpected event [%i] on channel [%p]",revents,obj);
		num=-1; /*to trigger an error*/
	}
	if (num>0){
358
		char *begin=obj->input_stream.write_ptr;
359 360 361
		obj->input_stream.write_ptr+=num;
		/*first null terminate the read buff*/
		*obj->input_stream.write_ptr='\0';
362
		if (num >50) /*to avoid tracing server based keep alives*/
363 364 365 366 367 368 369
			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);
370
		belle_sip_channel_parse_stream(obj);
371 372
		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*/);
373
		
jehan's avatar
jehan committed
374 375
	} else if (num == 0) {
		channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
jehan's avatar
jehan committed
376
		return BELLE_SIP_STOP;
jehan's avatar
jehan committed
377 378
	} else {
		belle_sip_error("Receive error on channel [%p]",obj);
jehan's avatar
jehan committed
379
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
jehan's avatar
jehan committed
380
		return BELLE_SIP_STOP;
jehan's avatar
jehan committed
381
	}
jehan's avatar
jehan committed
382
	return BELLE_SIP_CONTINUE;
Simon Morlat's avatar
Simon Morlat committed
383
}
384

385 386
static int channel_inactive_timeout(void *data, unsigned int event){
	belle_sip_channel_t *obj=(belle_sip_channel_t *)data;
387
	belle_sip_message("Channel [%p]: inactivity timeout reached.",obj);
388 389 390 391
	channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
	return BELLE_SIP_STOP;
}

392
static void update_inactivity_timer(belle_sip_channel_t *obj, int from_recv){
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
	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;
		}
	}
408 409
	if (from_recv)
		obj->last_recv_time=belle_sip_time_ms();
410
}
jehan's avatar
jehan committed
411

412
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){
413 414 415 416
	/*to initialize our base class:*/
	belle_sip_channel_set_socket(obj,-1,NULL);
	
	/*then initialize members*/
417
	obj->peer_cname=peer_cname ? belle_sip_strdup(peer_cname) : NULL;
418 419
	obj->peer_name=belle_sip_strdup(peername);
	obj->peer_port=peer_port;
420
	obj->stack=stack;
421
	if (bindip && strcmp(bindip,"::0")!=0 && strcmp(bindip,"0.0.0.0")!=0)
422 423
		obj->local_ip=belle_sip_strdup(bindip);
	obj->local_port=localport;
Simon Morlat's avatar
Simon Morlat committed
424
	obj->simulated_recv_return=1;/*not set*/
425 426 427 428 429 430
	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;
	}
431
	belle_sip_channel_input_stream_reset(&obj->input_stream);
432
	update_inactivity_timer(obj,FALSE);
433 434
}

435 436 437 438 439 440 441 442 443 444
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);
445
	belle_sip_channel_init(obj,stack,NULL,0,NULL,remoteip,peer_port);
446
	obj->peer_list=obj->current_peer=belle_sip_ip_address_to_addrinfo(ai.ai_family, obj->peer_name,obj->peer_port);
447 448
}

Simon Morlat's avatar
Simon Morlat committed
449
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
450 451 452 453 454 455
	belle_sip_socket_source_init((belle_sip_source_t*)obj
									, datafunc
									, obj
									, sock
									, BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_WRITE
									, -1);
456 457
}

458 459 460 461 462 463 464 465 466 467 468
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);
}

469 470 471 472
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*/
473
		return 1;
474
	}
475
	if (addr && obj->current_peer)
476
		return addr->ai_addrlen==obj->current_peer->ai_addrlen && memcmp(addr->ai_addr,obj->current_peer->ai_addr,addr->ai_addrlen)==0;
477 478 479
	return 0;
}

480 481 482 483 484
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;
}

485 486 487
int belle_sip_channel_is_reliable(const belle_sip_channel_t *obj){
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->reliable;
}
488

jehan's avatar
jehan committed
489 490 491 492 493 494 495 496 497 498 499
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;
	}
}
500

501
const char * belle_sip_channel_get_transport_name(const belle_sip_channel_t *obj){
502
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->transport;
503 504 505
}

int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
506
	update_inactivity_timer(obj,FALSE);
507 508 509 510
	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){
511
	update_inactivity_timer(obj,TRUE);
512 513 514
	return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->channel_recv(obj,buf,buflen);
}

515
void belle_sip_channel_close(belle_sip_channel_t *obj){
516
	if (BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->close)
517
		BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->close(obj); /*udp channel doesn't have close function*/
518 519
	belle_sip_main_loop_remove_source(obj->stack->ml,(belle_sip_source_t*)obj);
	belle_sip_source_uninit((belle_sip_source_t*)obj);
520 521
}

522
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
523
	return obj->current_peer;
524 525
}

jehan's avatar
jehan committed
526
belle_sip_message_t* belle_sip_channel_pick_message(belle_sip_channel_t *obj) {
jehan's avatar
jehan committed
527 528
	belle_sip_message_t* result=NULL;
	belle_sip_list_t* front;
529
	if ((front=obj->incoming_messages)!=NULL) {
jehan's avatar
jehan committed
530 531 532 533
		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
534 535
	return result;
}
536

Simon Morlat's avatar
Simon Morlat committed
537
static void channel_invoke_state_listener(belle_sip_channel_t *obj){
538 539 540
	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
541
	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
542 543
}

544 545 546 547 548
static void channel_invoke_state_listener_defered(belle_sip_channel_t *obj){
	channel_invoke_state_listener(obj);
	belle_sip_object_unref(obj);
}

549
static void belle_sip_channel_handle_error(belle_sip_channel_t *obj){
550 551 552 553 554 555 556 557 558 559 560
	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);
			belle_sip_channel_connect(obj);
			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*/
561 562 563
	
	obj->state=BELLE_SIP_CHANNEL_ERROR;
	/*Because error notification will in practice trigger the destruction of possible transactions and this channel,
564 565 566
	* 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.
	*/
567 568 569 570
	belle_sip_object_ref(obj);
	belle_sip_main_loop_do_later(obj->stack->ml,(belle_sip_callback_t)channel_invoke_state_listener_defered,obj);
}

571 572 573 574 575 576 577 578
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
579 580
}

581 582 583 584 585 586 587
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;
Simon Morlat's avatar
Simon Morlat committed
588
		channel_invoke_state_listener(obj);
589
	}
590
}
591

Simon Morlat's avatar
Simon Morlat committed
592
static void _send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
593
	char buffer[belle_sip_network_buffer_size];
594
	size_t len=0;
595
	int ret=0;
Ghislain MARY's avatar
Ghislain MARY committed
596
	belle_sip_error_code error=BELLE_SIP_OK;
Simon Morlat's avatar
Simon Morlat committed
597
	
598
	BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_sending,obj,msg);
Ghislain MARY's avatar
Ghislain MARY committed
599 600
	error=belle_sip_object_marshal((belle_sip_object_t*)msg,buffer,sizeof(buffer),&len);
	if ((error==BELLE_SIP_OK) && (len>0)){
601
		buffer[len]='\0';
602 603 604 605 606 607 608 609
		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
610
				,(int)len
Simon Morlat's avatar
Simon Morlat committed
611 612 613 614 615
				,belle_sip_channel_get_transport_name(obj)
				,obj->local_ip
				,obj->local_port
				,obj->peer_name
				,obj->peer_port);
616
			channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
Simon Morlat's avatar
Simon Morlat committed
617 618 619 620 621 622 623 624
		}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);
625
		}else{
Simon Morlat's avatar
Simon Morlat committed
626
			belle_sip_error("channel [%p]: message partly sent to [%s://%s:%i], sent: [%i/%i] bytes:\n%s"
jehan's avatar
jehan committed
627 628 629 630
								,obj
								,belle_sip_channel_get_transport_name(obj)
								,obj->peer_name
								,obj->peer_port
Simon Morlat's avatar
Simon Morlat committed
631
								,ret
Simon Morlat's avatar
Simon Morlat committed
632
								,(int)len
jehan's avatar
jehan committed
633
								,buffer);
634 635 636 637
		}
	}
}

Simon Morlat's avatar
Simon Morlat committed
638 639 640 641 642 643 644 645
/* 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){
646
	belle_sip_message("on_delayed_send_do(): sending now");
Simon Morlat's avatar
Simon Morlat committed
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
	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);
662
		belle_sip_message("channel %p: message sending delayed by %i ms",obj,obj->stack->tx_delay);
Simon Morlat's avatar
Simon Morlat committed
663 664
	}else _send_message(obj,msg);
}
665

Simon Morlat's avatar
Simon Morlat committed
666
void belle_sip_channel_prepare(belle_sip_channel_t *obj){
667
	channel_prepare_continue(obj);
Simon Morlat's avatar
Simon Morlat committed
668 669
}

670 671 672 673 674 675 676 677 678 679 680 681 682 683
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
684 685
	switch(obj->state){
		case BELLE_SIP_CHANNEL_INIT:
686
			belle_sip_channel_resolve(obj);
Simon Morlat's avatar
Simon Morlat committed
687 688
		break;
		case BELLE_SIP_CHANNEL_RES_DONE:
689
			belle_sip_channel_connect(obj);
Simon Morlat's avatar
Simon Morlat committed
690 691
		break;
		case BELLE_SIP_CHANNEL_READY:
692
			channel_process_queue(obj);
Simon Morlat's avatar
Simon Morlat committed
693 694 695
		break;
		default:
		break;
696
	}
697 698 699 700 701 702
}

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*/

703
	while((msg=channel_pop_outgoing(obj))!=NULL && obj->state==BELLE_SIP_CHANNEL_READY) {
704 705 706 707
		send_message(obj, msg);
		belle_sip_object_unref(msg);
	}

Simon Morlat's avatar
Simon Morlat committed
708
	belle_sip_object_unref(obj);
709 710
}

jehan's avatar
jehan committed
711
void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t slen){
712 713 714 715 716 717
	char name[NI_MAXHOST];
	char serv[NI_MAXSERV];

	if (obj->local_ip==NULL){
		int err=getnameinfo(addr,slen,name,sizeof(name),serv,sizeof(serv),NI_NUMERICHOST|NI_NUMERICSERV);
		if (err!=0){
718
			belle_sip_error("belle_sip_channel_set_ready(): getnameinfo() failed: %s",gai_strerror(err));
719 720 721 722 723 724 725 726 727 728
		}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);
}

729
static void channel_res_done(void *data, const char *name, struct addrinfo *ai_list){
730
	belle_sip_channel_t *obj=(belle_sip_channel_t*)data;
731 732 733 734
	if (obj->resolver_ctx){
		belle_sip_object_unref(obj->resolver_ctx);
		obj->resolver_ctx=NULL;
	}
735 736
	if (ai_list){
		obj->peer_list=obj->current_peer=ai_list;
737
		channel_set_state(obj,BELLE_SIP_CHANNEL_RES_DONE);
738
		channel_prepare_continue(obj);
739
	}else{
740
		belle_sip_error("%s: DNS resolution failed", __FUNCTION__);
741
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
742 743 744
	}
}

jehan's avatar
jehan committed
745
void belle_sip_channel_resolve(belle_sip_channel_t *obj){
746
	channel_set_state(obj,BELLE_SIP_CHANNEL_RES_IN_PROGRESS);
747 748 749 750
	if (belle_sip_stack_dns_srv_enabled(obj->stack))
		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->lp->ai_family, channel_res_done, obj);
	else
		obj->resolver_ctx=belle_sip_stack_resolve_a(obj->stack, obj->peer_name, obj->peer_port, obj->lp->ai_family, channel_res_done, obj);
751 752
	if (obj->resolver_ctx){
		belle_sip_object_ref(obj->resolver_ctx);
753
	}
jehan's avatar
jehan committed
754
	return ;
755 756
}

jehan's avatar
jehan committed
757
void belle_sip_channel_connect(belle_sip_channel_t *obj){
758 759
	char ip[64];
	
jehan's avatar
jehan committed
760
	channel_set_state(obj,BELLE_SIP_CHANNEL_CONNECTING);
761 762 763 764
	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
765
		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
766 767 768
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
	}
	return;
769 770 771
}

int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
772 773 774
	belle_sip_object_ref(msg);
	channel_push_outgoing(obj,msg);
	if (obj->state==BELLE_SIP_CHANNEL_INIT){
Simon Morlat's avatar
Simon Morlat committed
775
		belle_sip_channel_prepare(obj);
776 777 778
	}else if (obj->state==BELLE_SIP_CHANNEL_READY) {
		channel_process_queue(obj);
	}		
779 780 781
	return 0;
}

Simon Morlat's avatar
Simon Morlat committed
782 783 784 785
void belle_sip_channel_force_close(belle_sip_channel_t *obj){
	obj->force_close=1;
	channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
}
786

Simon Morlat's avatar
Simon Morlat committed
787 788 789 790 791 792 793 794 795 796 797 798
belle_sip_channel_t *belle_sip_channel_find_from_list_with_addrinfo(belle_sip_list_t *l, const belle_sip_hop_t *hop, const struct addrinfo *addr){
	belle_sip_list_t *elem;
	belle_sip_channel_t *chan;
	
	for(elem=l;elem!=NULL;elem=elem->next){
		chan=(belle_sip_channel_t*)elem->data;
		if (belle_sip_channel_matches(chan,hop,addr)){
			return chan;
		}
	}
	return NULL;
}
Simon Morlat's avatar
Simon Morlat committed
799 800
/* search a matching channel from a list according to supplied hop. The ai_family tells which address family is supported by the list of channels*/
belle_sip_channel_t *belle_sip_channel_find_from_list(belle_sip_list_t *l, int ai_family, const belle_sip_hop_t *hop){
Simon Morlat's avatar
Simon Morlat committed
801 802 803 804 805
	struct addrinfo *res=NULL;
	struct addrinfo hints={0};
	char portstr[20];
	belle_sip_channel_t *chan;

Simon Morlat's avatar
Simon Morlat committed
806
	hints.ai_family=ai_family;
Simon Morlat's avatar
Simon Morlat committed
807
	hints.ai_flags=AI_NUMERICHOST|AI_NUMERICSERV;
Simon Morlat's avatar
Simon Morlat committed
808 809
	if (ai_family==AF_INET6) hints.ai_flags=AI_V4MAPPED;
	
Simon Morlat's avatar
Simon Morlat committed
810 811 812 813 814 815 816 817
	snprintf(portstr,sizeof(portstr),"%i",hop->port);
	getaddrinfo(hop->host,portstr,&hints,&res);
	chan=belle_sip_channel_find_from_list_with_addrinfo(l,hop,res);
	if (res) freeaddrinfo(res);
	return chan;
}


818