Exemplo n.º 1
0
/*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.
 */
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){
	/*to initialize our base class:*/
	belle_sip_channel_set_socket(obj,-1,NULL);
	
	/*then initialize members*/
	obj->ai_family=AF_INET;
	obj->peer_cname=peer_cname ? belle_sip_strdup(peer_cname) : NULL;
	obj->peer_name=belle_sip_strdup(peername);
	obj->peer_port=peer_port;
	obj->stack=stack;
	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;
	}
	obj->local_port=localport;
	obj->simulated_recv_return=1;/*not set*/
	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;
	}
	belle_sip_channel_input_stream_reset(&obj->input_stream);
	update_inactivity_timer(obj,FALSE);
}
Exemplo n.º 2
0
static void belle_sip_channel_message_ready(belle_sip_channel_t *obj){
	belle_sip_message_t *msg=obj->input_stream.msg;
	belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg);
	if (bh) belle_sip_body_handler_end_transfer(bh);
	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);
	belle_sip_channel_input_stream_reset(&obj->input_stream);
}
Exemplo n.º 3
0
static int acquire_chuncked_body(belle_sip_channel_t *obj){
	belle_sip_channel_input_stream_t *st=&obj->input_stream;
	int readsize;
	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");
						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("Will get a chunk of %i bytes",(int)chunksize);
						st->chunk_size=chunksize;
						st->chunk_read_size=0;
						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;
			}
		}
		readsize=MIN(st->write_ptr-st->read_ptr,st->chunk_size-st->chunk_read_size);
		if (readsize>0){
			feed_body(obj,readsize);
			st->chunk_read_size+=readsize;
		}
		if (st->chunk_size==st->chunk_read_size){
			/*we have a chunk completed*/
			st->content_length+=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(st->write_ptr-st->read_ptr>0); /*no need to continue if nothing to read*/
	return BELLE_SIP_STOP;
}
Exemplo n.º 4
0
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj, int end_of_stream){
	int offset;
	size_t read_size=0;
	int num;
	
	while ((num=(obj->input_stream.write_ptr-obj->input_stream.read_ptr))>0){
	
		if (obj->input_stream.state == WAITING_MESSAGE_START) {
			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;
				}
			}

			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;
			}
		}

		if (obj->input_stream.state==MESSAGE_AQUISITION) {
			/*search for \r\n\r\n*/
			char* end_of_message=NULL;
			if ((end_of_message=strstr(obj->input_stream.read_ptr,"\r\n\r\n"))){
				int bytes_to_parse;
				char tmp;
				/*end of message found*/
				end_of_message+=4;/*add \r\n\r\n*/
				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.*/
				/*belle_sip_message("channel [%p] read message of [%i] bytes:\n%.40s...",obj, bytes_to_parse, obj->input_stream.read_ptr);*/
				obj->input_stream.msg=belle_sip_message_parse_raw(obj->input_stream.read_ptr
										,bytes_to_parse
										,&read_size);
				*end_of_message=tmp;
				obj->input_stream.read_ptr+=read_size;
				if (obj->input_stream.msg && read_size > 0){
					belle_sip_message("channel [%p] [%i] bytes parsed",obj,(int)read_size);
					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 (check_body(obj)){
						obj->input_stream.state=BODY_AQUISITION;
					} else {
						/*no body*/
						belle_sip_channel_message_ready(obj);
						continue;
					}
				}else{
					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;
					continue;
				}
			}else break; /*The message isn't finished to be receive, we need more data*/
		}

		if (obj->input_stream.state==BODY_AQUISITION) {
			if (acquire_body(obj,end_of_stream)==BELLE_SIP_STOP) break;
		}
	}
}