Пример #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
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;
}
Пример #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;
}
Пример #4
0
static void _send_message(belle_sip_channel_t *obj){
	char buffer[belle_sip_network_buffer_size];
	size_t len=0;
	belle_sip_error_code error=BELLE_SIP_OK;
	belle_sip_message_t *msg=obj->cur_out_message;
	belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg);
	size_t body_len=bh ? belle_sip_body_handler_get_size(bh) : 0;
	int sendret;
	size_t off;
	int ret;
	
	if (obj->ewouldblock_buffer){
		sendret=send_buffer(obj,(const char*)obj->ewouldblock_buffer+obj->ewouldblock_offset,obj->ewouldblock_size-obj->ewouldblock_offset);
		if (sendret>0){
			obj->ewouldblock_offset+=sendret;
			if (obj->ewouldblock_offset==obj->ewouldblock_size){
				free_ewouldblock_buffer(obj);
			}
			return; /*we prefer poll again to be sure we can write*/
		}else if (belle_sip_error_code_is_would_block(-sendret)) {
			/*we got an ewouldblock again. Nothing to do, we'll be called later in order to retry*/
			return;
		}else {/*error or disconnection case*/
			goto done;
		}
	}
	
	if (obj->out_state==OUTPUT_STREAM_SENDING_HEADERS){
		BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_sending,obj,msg);
		check_content_length(msg,body_len);
		error=belle_sip_object_marshal((belle_sip_object_t*)msg,buffer,sizeof(buffer)-1,&len);
		if (error!=BELLE_SIP_OK) {
			belle_sip_error("channel [%p] _send_message: marshaling failed.",obj);
			goto done;
		}
		/*send the headers and eventually the body if it fits in our buffer*/
		if (bh){
			size_t max_body_len=sizeof(buffer)-1-len;
			
			if (body_len>0 && body_len<=max_body_len){ /*if size is known and fits into our buffer, send together with headers*/
				belle_sip_body_handler_begin_transfer(bh);
				do{
					max_body_len=sizeof(buffer)-1-len;
					ret=belle_sip_body_handler_send_chunk(bh,msg,(uint8_t*)buffer+len,&max_body_len);
					len+=max_body_len;
				}while(ret==BELLE_SIP_CONTINUE);
				belle_sip_body_handler_end_transfer(bh);
			}else{
				if (body_len==0){
					belle_sip_fatal("Sending bodies whose size is not known must be done in chunked mode, which is not supported yet.");
				}
				belle_sip_body_handler_begin_transfer(bh);
				obj->out_state=OUTPUT_STREAM_SENDING_BODY;
			}
		}
		off=0;
		do{
			sendret=send_buffer(obj,buffer+off,len-off);
			if (sendret>0){
				off+=sendret;
				if (off==len){
					break;
				}
			}else if (belle_sip_error_code_is_would_block(-sendret)) {
				handle_ewouldblock(obj,buffer+off,len-off);
				return;
			}else {/*error or disconnection case*/
				goto done;
			}
		}while(1);
	}
	if (obj->out_state==OUTPUT_STREAM_SENDING_BODY){
		do{
			size_t chunk_len=sizeof(buffer)-1;
			ret=belle_sip_body_handler_send_chunk(bh,msg,(uint8_t*)buffer,&chunk_len);
			if (chunk_len!=0){
				off=0;
				do{
					sendret=send_buffer(obj,buffer+off,chunk_len-off);
					if (sendret>0){
						off+=sendret;
						if (off==chunk_len){
							break;
						}
					}else if (belle_sip_error_code_is_would_block(-sendret)) {
						handle_ewouldblock(obj,buffer+off,chunk_len-off);
						return;
					}else {/*error or disconnection case*/
						goto done;
					}
				}while(1);
			}
		}while(ret==BELLE_SIP_CONTINUE);
		belle_sip_body_handler_end_transfer(bh);
	}
	done:
		/*we get ready to send another message*/
		belle_sip_source_set_events((belle_sip_source_t*)obj,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR);
		free_ewouldblock_buffer(obj);
		obj->out_state=OUTPUT_STREAM_IDLE;
		belle_sip_object_unref(obj->cur_out_message);
		obj->cur_out_message=NULL;
}