예제 #1
0
static int send_keep_alive(belle_sip_channel_t* obj) {
	/*keep alive*/
	const char* crlfcrlf = "\r\n\r\n";
	int size=strlen(crlfcrlf);
	int err=belle_sip_channel_send(obj,crlfcrlf,size);
	
	if (err<=0 && !belle_sip_error_code_is_would_block(-err) && err!=-EINTR){
		belle_sip_error("channel [%p]: could not send [%i] bytes of keep alive from [%s://%s:%i]  to [%s:%i]"	,obj
			,size
			,belle_sip_channel_get_transport_name(obj)
			,obj->local_ip
			,obj->local_port
			,obj->peer_name
			,obj->peer_port);

		return -1;
	}else{
		belle_sip_message("channel [%p]: keep alive sent to [%s://%s:%i]"
							,obj
							,belle_sip_channel_get_transport_name(obj)
							,obj->peer_name
							,obj->peer_port);
		return 0;
	}
}
예제 #2
0
파일: channel.c 프로젝트: PeterXu/sipstack
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;
}
예제 #3
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;
}
예제 #4
0
static void http_channel_context_handle_io_error(belle_http_channel_context_t *ctx, belle_sip_channel_t *chan){
	belle_http_request_t *req=NULL;
	belle_sip_io_error_event_t ev={0};
	belle_sip_list_t *elem;

	/*if the error happens before attempting to send the message, the pending_requests is empty*/
	if (ctx->pending_requests==NULL) elem=chan->outgoing_messages;
	else elem=ctx->pending_requests;
	/*pop the requests for which this error is reported*/
	for(;elem!=NULL;elem=elem->next){
		req=(belle_http_request_t *)elem->data;
		/*else notify the app about the response received*/
		/*TODO: would be nice to put the message in the event*/
		ev.source=(belle_sip_object_t*)ctx->provider;
		ev.host=chan->peer_cname;
		ev.port=chan->peer_port;
		ev.transport=belle_sip_channel_get_transport_name(chan);
		BELLE_HTTP_REQUEST_INVOKE_LISTENER(req,process_io_error,&ev);
		if( req->background_task_id ){
			belle_sip_warning("IO Error on HTTP request: ending bg task id=[%x]", req->background_task_id);
			belle_sip_end_background_task(req->background_task_id);
			req->background_task_id = 0;
		}
	}

}
예제 #5
0
파일: channel.c 프로젝트: PeterXu/sipstack
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;
	}
}
예제 #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;
}
예제 #7
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;
}
예제 #8
0
static void on_channel_state_changed(belle_sip_channel_listener_t *l, belle_sip_channel_t *chan, belle_sip_channel_state_t state){
	belle_sip_transaction_t *t=(belle_sip_transaction_t*)l;
	belle_sip_io_error_event_t ev;
	belle_sip_transaction_state_t tr_state=belle_sip_transaction_get_state((belle_sip_transaction_t*)t);

	belle_sip_message("transaction [%p] channel state changed to [%s]"
						,t
						,belle_sip_channel_state_to_string(state));
	switch(state){
		case BELLE_SIP_CHANNEL_READY:
			if (tr_state==BELLE_SIP_TRANSACTION_INIT && BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_client_transaction_t) ){
				belle_sip_client_transaction_t *ct = (belle_sip_client_transaction_t*) t;
				BELLE_SIP_OBJECT_VPTR(ct,belle_sip_client_transaction_t)->send_request(ct);
			}
		break;
		case BELLE_SIP_CHANNEL_DISCONNECTED:
		case BELLE_SIP_CHANNEL_ERROR:
			ev.transport=belle_sip_channel_get_transport_name(chan);
			ev.source=BELLE_SIP_OBJECT(t);
			ev.port=chan->peer_port;
			ev.host=chan->peer_name;
			if ( tr_state!=BELLE_SIP_TRANSACTION_COMPLETED
				&& tr_state!=BELLE_SIP_TRANSACTION_CONFIRMED
				&& tr_state!=BELLE_SIP_TRANSACTION_ACCEPTED
				&& tr_state!=BELLE_SIP_TRANSACTION_TERMINATED) {
				BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(((belle_sip_transaction_t*)t),process_io_error,&ev);
			}
			if (t->timed_out)
				notify_timeout((belle_sip_transaction_t*)t);

			belle_sip_transaction_terminate(t);
		break;
		default:
			/*ignored*/
		break;
	}
}
예제 #9
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;
}
예제 #10
0
static void provider_remove_channel(belle_http_provider_t *obj, belle_sip_channel_t *chan){
	belle_sip_list_t **channels=provider_get_channels(obj,belle_sip_channel_get_transport_name(chan));
	*channels=belle_sip_list_remove(*channels,chan);
	belle_sip_message("channel [%p] removed from http provider.",obj);
	belle_sip_object_unref(chan);
}