Ejemplo n.º 1
0
void belle_sip_channel_connect(belle_sip_channel_t *obj){
	char ip[64];
	
	channel_set_state(obj,BELLE_SIP_CHANNEL_CONNECTING);
	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)) {
		belle_sip_error("Cannot connect to [%s://%s:%i]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port);
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
	}
	return;
}
Ejemplo n.º 2
0
static void channel_res_done(void *data, const char *name, struct addrinfo *ai_list){
	belle_sip_channel_t *obj=(belle_sip_channel_t*)data;
	if (obj->resolver_ctx){
		belle_sip_object_unref(obj->resolver_ctx);
		obj->resolver_ctx=NULL;
	}
	if (ai_list){
		obj->peer_list=obj->current_peer=ai_list;
		channel_set_state(obj,BELLE_SIP_CHANNEL_RES_DONE);
		channel_prepare_continue(obj);
	}else{
		belle_sip_error("%s: DNS resolution failed", __FUNCTION__);
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
	}
}
Ejemplo n.º 3
0
static int belle_sip_channel_process_read_data(belle_sip_channel_t *obj){
	int num;
	int ret=BELLE_SIP_CONTINUE;

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

	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);
	} else {
		belle_sip_message("channel [%p]: simulating recv() returning %i",obj,obj->simulated_recv_return);
		num=obj->simulated_recv_return;
	}
	if (num>0){
		char *begin=obj->input_stream.write_ptr;
		char *logbuf=make_logbuf(BELLE_SIP_LOG_MESSAGE,begin,num);
		obj->input_stream.write_ptr+=num;
		/*first null terminate the read buff*/
		*obj->input_stream.write_ptr='\0';
		if (num>20) /*to avoid tracing server based keep alives*/
			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);
		belle_sip_channel_process_stream(obj,FALSE);
	} else if (num == 0) {
		/*before closing the channel, check if there was a pending message to receive, whose body acquisition is to be finished.*/
		belle_sip_channel_process_stream(obj,TRUE);
		channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
		ret=BELLE_SIP_STOP;
	} else if (belle_sip_error_code_is_would_block(-num)){
		belle_sip_message("channel [%p]: recv() EWOULDBLOCK",obj);
		ret=BELLE_SIP_CONTINUE;
	}else{
		belle_sip_error("Receive error on channel [%p]",obj);
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
		ret=BELLE_SIP_STOP;
	}
	if (obj->input_stream.state == WAITING_MESSAGE_START)
		channel_end_recv_background_task(obj);
	return ret;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
void belle_sip_channel_resolve(belle_sip_channel_t *obj){
	channel_set_state(obj,BELLE_SIP_CHANNEL_RES_IN_PROGRESS);
	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);
	else
		obj->resolver_ctx=belle_sip_stack_resolve_a(obj->stack, obj->peer_name, obj->peer_port, obj->ai_family, channel_res_done, obj);
	if (obj->resolver_ctx){
		belle_sip_object_ref(obj->resolver_ctx);
	}
	return ;
}
Ejemplo n.º 6
0
void belle_sip_channel_connect(belle_sip_channel_t *obj){
	char ip[64];
	int port=obj->peer_port;

	channel_set_state(obj,BELLE_SIP_CHANNEL_CONNECTING);
	belle_sip_addrinfo_to_ip(obj->current_peer,ip,sizeof(ip),&port);
	/* update peer_port as it may have been overriden by SRV resolution*/
	if (port!=obj->peer_port){
		/*the SRV resolution provided a port number that must be used*/
		obj->srv_overrides_port=TRUE;
		obj->peer_port=port;
	}
	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)) {
		belle_sip_error("Cannot connect to [%s://%s:%i]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port);
		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
	}
	return;
}
Ejemplo n.º 7
0
static int send_buffer(belle_sip_channel_t *obj, const char *buffer, size_t size){
	int ret=0;
	char *logbuf=NULL;

	if (obj->stack->send_error == 0){
		ret=belle_sip_channel_send(obj,buffer,size);
	}else if (obj->stack->send_error<0){
		/*for testing purpose only */
		ret=obj->stack->send_error;
	} else {
		ret=size; /*to silently discard message*/
	}

	if (ret<0){
		if (!belle_sip_error_code_is_would_block(-ret)){
			belle_sip_error("channel [%p]: could not send [%i] bytes from [%s://%s:%i] to [%s:%i]"	,obj
				,(int)size
				,belle_sip_channel_get_transport_name(obj)
				,obj->local_ip
				,obj->local_port
				,obj->peer_name
				,obj->peer_port);
			channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
		}/*ewouldblock error has to be handled by caller*/
	}else if (size==(size_t)ret){
		logbuf=make_logbuf(BELLE_SIP_LOG_MESSAGE, buffer,size);
		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);
	}else{
		logbuf=make_logbuf(BELLE_SIP_LOG_MESSAGE,buffer,ret);
		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);
	}
	if (logbuf) belle_sip_free(logbuf);
	return ret;
}
Ejemplo n.º 8
0
static int keep_alive_timer_func(void *user_data, unsigned int events) {
	belle_sip_listening_point_t* lp=(belle_sip_listening_point_t*)user_data;
	belle_sip_list_t* iterator;
	belle_sip_channel_t* channel;
	belle_sip_list_t *to_be_closed=NULL;

	for (iterator=lp->channels;iterator!=NULL;iterator=iterator->next) {
		channel=(belle_sip_channel_t*)iterator->data;
		if (channel->state == BELLE_SIP_CHANNEL_READY && send_keep_alive(channel)==-1) { /*only send keep alive if ready*/
			to_be_closed=belle_sip_list_append(to_be_closed,channel);
		}
	}
	for (iterator=to_be_closed;iterator!=NULL;iterator=iterator->next){
		channel=(belle_sip_channel_t*)iterator->data;
		channel_set_state(channel,BELLE_SIP_CHANNEL_ERROR);
		belle_sip_channel_close(channel);
	}
	belle_sip_list_free(to_be_closed);
	return BELLE_SIP_CONTINUE_WITHOUT_CATCHUP;
}
Ejemplo n.º 9
0
static void belle_sip_channel_handle_error(belle_sip_channel_t *obj){
	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_main_loop_do_later(obj->stack->ml,(belle_sip_callback_t)channel_connect_next,belle_sip_object_ref(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*/
	
	obj->state=BELLE_SIP_CHANNEL_ERROR;
	channel_end_send_background_task(obj);
	/*Because error notification will in practice trigger the destruction of possible transactions and this channel,
	* 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.
	*/
	belle_sip_main_loop_do_later(obj->stack->ml,(belle_sip_callback_t)channel_invoke_state_listener_defered,belle_sip_object_ref(obj));
}
Ejemplo n.º 10
0
static int tls_process_data(belle_sip_channel_t *obj,unsigned int revents){
	belle_sip_tls_channel_t* channel=(belle_sip_tls_channel_t*)obj;

	if (obj->state == BELLE_SIP_CHANNEL_CONNECTING ) {
		if (!channel->socket_connected) {
			channel->socklen=sizeof(channel->ss);
			if (finalize_stream_connection((belle_sip_stream_channel_t*)obj,revents,(struct sockaddr*)&channel->ss,&channel->socklen)) {
				goto process_error;
			}
			belle_sip_message("Channel [%p]: Connected at TCP level, now doing TLS handshake",obj);
			channel->socket_connected=1;
			belle_sip_source_set_events((belle_sip_source_t*)channel,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR);
			belle_sip_source_set_timeout((belle_sip_source_t*)obj,belle_sip_stack_get_transport_timeout(obj->stack));
			if (tls_process_handshake(obj)==-1) goto process_error;
		}else{
			if (revents & BELLE_SIP_EVENT_READ){
				if (tls_process_handshake(obj)==-1) goto process_error;
			}else if (revents==BELLE_SIP_EVENT_TIMEOUT){
				belle_sip_error("channel [%p]: SSL handshake took too much time.",obj);
				goto process_error;
			}else{
				belle_sip_warning("channeEHHCXCCCl [%p]: unexpected event [%i] during TLS handshake.",obj,revents);
			}
		}
	} else if ( obj->state == BELLE_SIP_CHANNEL_READY) {
		return belle_sip_channel_process_data(obj,revents);
	} else {
		belle_sip_warning("Unexpected event [%i], for channel [%p]",revents,channel);
		return BELLE_SIP_STOP;
	}
	return BELLE_SIP_CONTINUE;
	
process_error:
	belle_sip_error("Cannot connect to [%s://%s:%i]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port);
	channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
	return BELLE_SIP_STOP;
}
Ejemplo n.º 11
0
void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t slen){
	char name[NI_MAXHOST];
	char serv[NI_MAXSERV];

	if (obj->local_ip==NULL){
		struct sockaddr_storage saddr;
		socklen_t slen2=sizeof(saddr);
		int err;
		
		belle_sip_address_remove_v4_mapping(addr,(struct sockaddr*) &saddr,&slen2);
		
		err=getnameinfo((struct sockaddr*)&saddr,slen,name,sizeof(name),serv,sizeof(serv),NI_NUMERICHOST|NI_NUMERICSERV);
		if (err!=0){
			belle_sip_error("belle_sip_channel_set_ready(): getnameinfo() failed: %s",gai_strerror(err));
		}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);
	channel_end_send_background_task(obj);
}
Ejemplo n.º 12
0
static int channel_inactive_timeout(void *data, unsigned int event){
	belle_sip_channel_t *obj=(belle_sip_channel_t *)data;
	belle_sip_message("Channel [%p]: inactivity timeout reached.",obj);
	channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
	return BELLE_SIP_STOP;
}
Ejemplo n.º 13
0
void belle_sip_channel_force_close(belle_sip_channel_t *obj){
	obj->force_close=1;
	channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
}