static int nict_on_timer_E(belle_sip_nict_t *obj){ belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj; const belle_sip_timer_config_t *cfg=belle_sip_transaction_get_timer_config(base); switch(base->state){ case BELLE_SIP_TRANSACTION_TRYING: { /*reset the timer */ unsigned int prev_timeout=belle_sip_source_get_timeout(obj->timer_E); belle_sip_source_set_timeout(obj->timer_E,MIN(2*prev_timeout,(unsigned int)cfg->T2)); belle_sip_message("nict_on_timer_E: sending retransmission"); belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)base->request); } break; case BELLE_SIP_TRANSACTION_PROCEEDING: belle_sip_source_set_timeout(obj->timer_E,cfg->T2); belle_sip_message("nict_on_timer_E: sending retransmission"); belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)base->request); break; default: /*if we are not in these cases, timer_E does nothing, so remove it*/ return BELLE_SIP_STOP; break; } return BELLE_SIP_CONTINUE; }
static void cast_test(void) { belle_sip_stack_t *stack=belle_sip_stack_new(NULL); belle_sip_listening_point_t *lp=belle_sip_stack_create_listening_point(stack,"0.0.0.0",7060,"UDP"); belle_sip_provider_t *provider; belle_sip_request_t *req=belle_sip_request_new(); belle_sip_response_t *resp=belle_sip_response_new(); belle_sip_message_t *msg; int tmp; BC_ASSERT_PTR_NOT_NULL(stack); BC_ASSERT_PTR_NOT_NULL(lp); provider=belle_sip_stack_create_provider(stack,lp); BC_ASSERT_PTR_NOT_NULL(provider); BC_ASSERT_PTR_NOT_NULL(req); BC_ASSERT_PTR_NOT_NULL(resp); belle_sip_message("Casting belle_sip_request_t to belle_sip_message_t"); msg=BELLE_SIP_MESSAGE(req); BC_ASSERT_PTR_NOT_NULL(msg); belle_sip_message("Ok."); belle_sip_message("Casting belle_sip_response_t to belle_sip_message_t"); msg=BELLE_SIP_MESSAGE(resp); BC_ASSERT_PTR_NOT_NULL(msg); belle_sip_message("Ok."); tmp=BELLE_SIP_IS_INSTANCE_OF(req,belle_sip_response_t); belle_sip_message("Casting belle_sip_request_t to belle_sip_response_t: %s",tmp ? "yes" : "no"); BC_ASSERT_EQUAL(tmp,0,int,"%d"); belle_sip_object_unref(req); belle_sip_object_unref(resp); belle_sip_object_unref(provider); belle_sip_object_unref(stack); }
static void caller_process_response_event(void *user_ctx, const belle_sip_response_event_t *event){ belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); belle_sip_header_from_t* from=belle_sip_message_get_header_by_type(belle_sip_response_event_get_response(event),belle_sip_header_from_t); belle_sip_header_cseq_t* invite_cseq=belle_sip_message_get_header_by_type(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)),belle_sip_header_cseq_t); belle_sip_request_t* ack; belle_sip_dialog_t* dialog; int status; if (!belle_sip_uri_equals(BELLE_SIP_URI(user_ctx),belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from)))) { belle_sip_message("Message [%p] not for caller, skipping",belle_sip_response_event_get_response(event)); return; /*not for the caller*/ } status = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)); belle_sip_message("caller_process_response_event [%i]",status); if (BC_ASSERT_PTR_NOT_NULL(client_transaction)) { dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(client_transaction)); if (BC_ASSERT_PTR_NOT_NULL(dialog)) { BC_ASSERT_PTR_EQUAL(caller_dialog,dialog); if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_NULL) { BC_ASSERT_EQUAL(status,100, int, "%d"); } else if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_EARLY){ BC_ASSERT_EQUAL(status,180, int, "%d"); /*send 200ok from callee*/ belle_sip_server_transaction_send_response(inserv_transaction,ok_response); belle_sip_object_unref(ok_response); ok_response=NULL; } else if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_CONFIRMED) {
static int is_contact_address_acurate(const belle_sip_refresher_t* refresher,belle_sip_request_t* request) { belle_sip_header_contact_t* contact; if ((contact = get_first_contact_in_unknown_state(request))){ /*check if contact ip/port is consistant with public channel ip/port*/ int channel_public_port = refresher->transaction->base.channel->public_port; int contact_port = belle_sip_uri_get_listening_port(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact))); const char* channel_public_ip = refresher->transaction->base.channel->public_ip; const char* contact_ip = belle_sip_uri_get_host(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact))); if (channel_public_port == contact_port && channel_public_ip && contact_ip && strcmp(channel_public_ip,contact_ip) == 0) { /*nothing to do contact is accurate*/ belle_sip_header_contact_set_unknown(contact,FALSE); return TRUE; } else { belle_sip_message("Refresher [%p]: contact address [%s:%i] does not match channel address[%s:%i] on channel [%p]" ,refresher ,contact_ip ,contact_port ,channel_public_ip ,channel_public_port ,refresher->transaction->base.channel); return FALSE; } } else { belle_sip_message("Refresher [%p]: has no contact for request [%p].", refresher,request); return TRUE; } }
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; }
int belle_sip_dialog_handle_ack(belle_sip_dialog_t *obj, belle_sip_request_t *ack){ belle_sip_header_cseq_t *cseq=belle_sip_message_get_header_by_type(ack,belle_sip_header_cseq_t); if (obj->needs_ack && belle_sip_header_cseq_get_seq_number(cseq)==obj->remote_cseq){ belle_sip_message("Incoming INVITE has ACK, dialog is happy"); obj->needs_ack=FALSE; belle_sip_dialog_stop_200Ok_retrans(obj); belle_sip_dialog_process_queue(obj); return 0; } belle_sip_message("Dialog ignoring incoming ACK (surely a retransmission)"); return -1; }
int belle_sip_tls_listening_point_set_root_ca(belle_sip_tls_listening_point_t *lp, const char *path){ if (lp->root_ca){ belle_sip_free(lp->root_ca); lp->root_ca=NULL; } if (path){ lp->root_ca=belle_sip_strdup(path); belle_sip_message("Root ca path set to %s",lp->root_ca); } else { belle_sip_message("Root ca path disabled"); } return 0; }
int belle_tls_verify_policy_set_root_ca(belle_tls_verify_policy_t *obj, const char *path){ if (obj->root_ca){ belle_sip_free(obj->root_ca); obj->root_ca=NULL; } if (path){ obj->root_ca=belle_sip_strdup(path); belle_sip_message("Root ca path set to %s",obj->root_ca); } else { belle_sip_message("Root ca path disabled"); } return 0; }
void belle_sip_object_dump_active_objects(void){ belle_sip_list_t *elem; if (all_objects){ belle_sip_message("List of leaked objects:"); for(elem=all_objects;elem!=NULL;elem=elem->next){ belle_sip_object_t *obj=(belle_sip_object_t*)elem->data; char* content= belle_sip_object_to_string(obj); belle_sip_message("%s(%p) ref=%i, content [%10s...]",obj->vptr->type_name,obj,obj->ref,content); belle_sip_free(content); } }else belle_sip_message("No objects leaked."); }
/* * return 0 if dialog handle the 200ok * */ static int belle_sip_dialog_handle_200Ok(belle_sip_dialog_t *obj, belle_sip_response_t *msg){ if (obj->last_out_ack){ belle_sip_header_cseq_t *cseq=belle_sip_message_get_header_by_type(msg,belle_sip_header_cseq_t); if (cseq){ belle_sip_header_cseq_t *ack_cseq=belle_sip_message_get_header_by_type(obj->last_out_ack,belle_sip_header_cseq_t); if (belle_sip_header_cseq_get_seq_number(cseq)==belle_sip_header_cseq_get_seq_number(ack_cseq)){ /*pass for retransmission*/ belle_sip_message("Dialog retransmitting last ack automatically"); belle_sip_provider_send_request(obj->provider,obj->last_out_ack); return 0; }else belle_sip_message("No already created ACK matching 200Ok for dialog [%p]",obj); } } return -1; }
void belle_sip_client_transaction_notify_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){ belle_sip_transaction_t *base=(belle_sip_transaction_t*)t; belle_sip_request_t* req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t)); const char* method = belle_sip_request_get_method(req); belle_sip_response_event_t event; belle_sip_dialog_t *dialog=base->dialog; int status_code = belle_sip_response_get_status_code(resp); if (base->last_response) belle_sip_object_unref(base->last_response); base->last_response=(belle_sip_response_t*)belle_sip_object_ref(resp); if (dialog){ if (status_code>=101 && status_code<300 && strcmp(method,"INVITE")==0 && (dialog->state==BELLE_SIP_DIALOG_EARLY || dialog->state==BELLE_SIP_DIALOG_CONFIRMED)){ /*make sure this response matches the current dialog, or creates a new one*/ if (!belle_sip_dialog_match(dialog,(belle_sip_message_t*)resp,FALSE)){ dialog=belle_sip_provider_find_dialog_from_message(t->base.provider,(belle_sip_message_t*)resp,FALSE); if (!dialog){ dialog=belle_sip_provider_create_dialog_internal(t->base.provider,BELLE_SIP_TRANSACTION(t),FALSE);/*belle_sip_dialog_new(base);*/ belle_sip_message("Handling response creating a new dialog !"); } } } } else if (should_dialog_be_created(t,resp)) { dialog=belle_sip_provider_create_dialog_internal(t->base.provider,BELLE_SIP_TRANSACTION(t),FALSE); } if (dialog && belle_sip_dialog_update(dialog,BELLE_SIP_TRANSACTION(t),FALSE)) { /* retransmition, just return*/ belle_sip_message("[%p] is a 200 ok retransmition on dialog [%p], skiping",resp,dialog); return; } event.source=(belle_sip_object_t*)base->provider; event.client_transaction=t; event.dialog=dialog; event.response=(belle_sip_response_t*)resp; BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(((belle_sip_transaction_t*)t),process_response_event,&event); /*check that 200Ok for INVITEs have been acknowledged by listener*/ if (dialog && strcmp(method,"INVITE")==0){ belle_sip_dialog_check_ack_sent(dialog); } /*report a server having internal errors for REGISTER to the channel, in order to go to a fallback IP*/ if (status_code == 500 && strcmp(method,"REGISTER") == 0){ belle_sip_channel_notify_server_error(base->channel); } }
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; }
static void queue_message_delayed(belle_sip_channel_t *obj, belle_sip_message_t *msg){ delay_send_t *ctx=belle_sip_malloc(sizeof(delay_send_t)); ctx->chan=(belle_sip_channel_t*)belle_sip_object_ref(obj); ctx->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,ctx,obj->stack->tx_delay); belle_sip_message("channel %p: message sending delayed by %i ms",obj,obj->stack->tx_delay); }
static void test_overflow(void){ belle_sdp_session_description_t* sdp; belle_sip_list_t *mds; belle_sdp_media_description_t *vmd; int i; const size_t orig_buffsize=1024; size_t buffsize=orig_buffsize; char *buffer=belle_sip_malloc0(buffsize); size_t offset=0; sdp=belle_sdp_session_description_parse(big_sdp); CU_ASSERT_PTR_NOT_NULL(sdp); mds=belle_sdp_session_description_get_media_descriptions(sdp); CU_ASSERT_PTR_NOT_NULL(mds); CU_ASSERT_PTR_NOT_NULL(mds->next); vmd=(belle_sdp_media_description_t*)mds->next->data; for(i=0;i<16;i++){ belle_sdp_media_description_add_attribute(vmd,belle_sdp_attribute_create("candidate","2 1 UDP 1694498815 82.65.223.97 9078 typ srflx raddr 192.168.0.2 rport 9078")); } CU_ASSERT_EQUAL(belle_sip_object_marshal(BELLE_SIP_OBJECT(sdp),buffer,buffsize,&offset),BELLE_SIP_BUFFER_OVERFLOW); belle_sip_message("marshal size is %i",(int)offset); CU_ASSERT_TRUE(offset==buffsize); belle_sip_object_unref(sdp); belle_sip_free(buffer); }
static int acquire_body_simple(belle_sip_channel_t *obj, int end_of_stream){ int content_length=obj->input_stream.content_length; size_t to_read=obj->input_stream.write_ptr-obj->input_stream.read_ptr; belle_sip_message_t *msg=obj->input_stream.msg; belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg); size_t cursize=belle_sip_body_handler_get_transfered_size(bh); if ((cursize == 0) && (to_read == 0)) { /** * No data has been received yet, so do not call feed_body() with a size * of 0 that is meaning that the transfer is finished. */ } else { to_read=MIN(content_length-cursize, to_read); feed_body(obj,to_read); } if (end_of_stream || belle_sip_body_handler_get_transfered_size(bh)>=content_length){ /*great body completed*/ belle_sip_message("channel [%p] read [%i] bytes of body from [%s:%i]" ,obj ,content_length ,obj->peer_name ,obj->peer_port); belle_sip_channel_message_ready(obj); return BELLE_SIP_CONTINUE; } /*body is not finished, we need more data*/ return BELLE_SIP_STOP; }
static void client_process_auth_requested(void *obj, belle_sip_auth_event_t *event){ BELLESIP_UNUSED(obj); belle_sip_message("process_auth_requested requested for [%s@%s]" ,belle_sip_auth_event_get_username(event) ,belle_sip_auth_event_get_realm(event)); belle_sip_auth_event_set_passwd(event,PASSWD); }
static void client_process_response_event(void *obj, const belle_sip_response_event_t *event){ //belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); endpoint_t* endpoint = (endpoint_t*)obj; int status = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)); belle_sip_message("caller_process_response_event [%i]",status); switch (status) { case 200: endpoint->stat.twoHundredOk++; if (endpoint->connection_family!=AF_UNSPEC){ const char *host; int family_found; belle_sip_header_contact_t *ct=belle_sip_message_get_header_by_type( (belle_sip_message_t*)belle_sip_response_event_get_response(event),belle_sip_header_contact_t); CU_ASSERT_PTR_NOT_NULL_FATAL(ct); host=belle_sip_uri_get_host(belle_sip_header_address_get_uri((belle_sip_header_address_t*)ct)); if (strchr(host,':')) family_found=AF_INET6; else family_found=AF_INET; CU_ASSERT_TRUE(family_found==endpoint->connection_family); } break; case 401:endpoint->stat.fourHundredOne++; break; default: break; } }
static void channel_end_recv_background_task(belle_sip_channel_t *obj){ if (obj->recv_bg_task_id){ belle_sip_message("channel [%p]: ending recv background task with id=[%x].",obj,obj->recv_bg_task_id); belle_sip_end_background_task(obj->recv_bg_task_id); obj->recv_bg_task_id=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; } }
belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* transaction) { belle_sip_refresher_t* refresher; belle_sip_transaction_state_t state=belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(transaction)); belle_sip_request_t* request = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(transaction)); int is_register=strcmp("REGISTER",belle_sip_request_get_method(request))==0; refresher = (belle_sip_refresher_t*)belle_sip_object_new(belle_sip_refresher_t); refresher->transaction=transaction; refresher->state=stopped; refresher->number_of_retry=0; belle_sip_object_ref(transaction); refresher->retry_after=DEFAULT_RETRY_AFTER; if (belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(transaction))) { set_or_update_dialog(refresher, belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(transaction))); } belle_sip_provider_add_internal_sip_listener(transaction->base.provider,BELLE_SIP_LISTENER(refresher), is_register); if (set_expires_from_trans(refresher)==-1){ belle_sip_error("Unable to extract refresh value from transaction [%p]",transaction); } if (belle_sip_transaction_state_is_transient(state)) { belle_sip_message("Refresher [%p] takes ownership of transaction [%p]",refresher,transaction); transaction->base.is_internal=1; refresher->state=started; }else{ belle_sip_refresher_start(refresher); } return refresher; }
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; }
static int set_expires_from_trans(belle_sip_refresher_t* refresher) { belle_sip_transaction_t* transaction = BELLE_SIP_TRANSACTION(refresher->transaction); belle_sip_response_t*response=transaction->last_response; belle_sip_request_t*request=belle_sip_transaction_get_request(transaction); belle_sip_header_expires_t* expires_header=belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t); belle_sip_header_contact_t* contact_header; refresher->obtained_expires=-1; if (strcmp("REGISTER",belle_sip_request_get_method(request))==0 || expires_header /*if request has an expire header, refresher can always work*/) { if (expires_header) refresher->target_expires = belle_sip_header_expires_get_expires(expires_header); /*An "expires" parameter on the "Contact" header has no semantics for * SUBSCRIBE and is explicitly not equivalent to an "Expires" header in * a SUBSCRIBE request or response. */ if (strcmp("REGISTER",belle_sip_request_get_method(request))==0){ if (!expires_header && (contact_header=belle_sip_message_get_header_by_type((belle_sip_message_t*)request,belle_sip_header_contact_t))){ int ct_expires=belle_sip_header_contact_get_expires(BELLE_SIP_HEADER_CONTACT(contact_header)); if (ct_expires!=-1) refresher->target_expires=ct_expires; } /*check in response also to get the obtained expires*/ if ((contact_header=belle_sip_refresher_get_contact(refresher))!=NULL){ /*matching contact, check for its possible expires param*/ refresher->obtained_expires=belle_sip_header_contact_get_expires(BELLE_SIP_HEADER_CONTACT(contact_header)); } } if (refresher->obtained_expires==-1){ /*no contact with expire or not relevant, looking for Expires header*/ if (response && (expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_EXPIRES))) { refresher->obtained_expires = belle_sip_header_expires_get_expires(expires_header); } } if (refresher->obtained_expires==-1) { belle_sip_message("Neither Expires header nor corresponding Contact header found, checking from original request"); refresher->obtained_expires=refresher->target_expires; }else if (refresher->target_expires>0 && refresher->obtained_expires==0){ const char* reason = response ? belle_sip_response_get_reason_phrase(response) : NULL; /*check this case because otherwise we are going to loop fast in sending refresh requests.*/ /*"Test account created" is a special reason given by testers when we create temporary account. Since this is a bit of hack, we can ignore logging in that case*/ if (reason && strcmp(reason, "Test account created") != 0) { belle_sip_warning("Server replied with 0 expires, what does that mean?"); } /*suppose it's a server bug and assume our target_expires is understood.*/ refresher->obtained_expires=refresher->target_expires; } } else if (strcmp("INVITE",belle_sip_request_get_method(request))==0) { belle_sip_error("Refresher does not support INVITE yet"); return -1; } else { belle_sip_error("Refresher does not support [%s] yet",belle_sip_request_get_method(request)); return -1; } return 0; }
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ BELLESIP_UNUSED(user_ctx); BELLESIP_UNUSED(event); belle_sip_message("process_io_error, exiting main loop"); belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack)); io_error_count++; /*CU_ASSERT(CU_FALSE);*/ }
static void callee_process_request_event(void *user_ctx, const belle_sip_request_event_t *event) { belle_sip_dialog_t* dialog; belle_sip_response_t* ringing_response; belle_sip_header_content_type_t* content_type ; belle_sip_header_content_length_t* content_length; belle_sip_server_transaction_t* server_transaction = belle_sip_request_event_get_server_transaction(event); belle_sip_header_to_t* to=belle_sip_message_get_header_by_type(belle_sip_request_event_get_request(event),belle_sip_header_to_t); const char* method; if (!belle_sip_uri_equals(BELLE_SIP_URI(user_ctx),belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to)))) { belle_sip_message("Message [%p] not for callee, skipping",belle_sip_request_event_get_request(event)); return; /*not for the callee*/ } method = belle_sip_request_get_method(belle_sip_request_event_get_request(event)); if (!server_transaction && strcmp(method,"ACK")!=0) { server_transaction= belle_sip_provider_create_server_transaction(prov,belle_sip_request_event_get_request(event)); } belle_sip_message("callee_process_request_event received [%s] message",method); dialog = belle_sip_request_event_get_dialog(event); if (!dialog ) { BC_ASSERT_STRING_EQUAL_FATAL("INVITE",method); dialog=belle_sip_provider_create_dialog(prov,BELLE_SIP_TRANSACTION(server_transaction)); callee_dialog=dialog; inserv_transaction=server_transaction; } if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_NULL) { ringing_response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)),180); /*prepare 200ok*/ ok_response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)),200); content_length= belle_sip_header_content_length_create(strlen(sdp)); content_type = belle_sip_header_content_type_create("application","sdp"); belle_sip_message_add_header(BELLE_SIP_MESSAGE(ok_response),BELLE_SIP_HEADER(content_type)); belle_sip_message_add_header(BELLE_SIP_MESSAGE(ok_response),BELLE_SIP_HEADER(content_length)); belle_sip_message_set_body(BELLE_SIP_MESSAGE(ok_response),sdp,strlen(sdp)); belle_sip_object_ref(ok_response); /*only send ringing*/ belle_sip_server_transaction_send_response(server_transaction,ringing_response); } else if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_CONFIRMED) { /*time to send bye*/ belle_sip_client_transaction_t* client_transaction = belle_sip_provider_create_client_transaction(prov,belle_sip_dialog_create_request(dialog,"BYE")); belle_sip_client_transaction_send_request(client_transaction); } else { belle_sip_warning("Unexpected state [%s] for dialog [%p]",belle_sip_dialog_state_to_string(belle_sip_dialog_get_state(dialog)),dialog ); } }
void belle_sip_stack_set_timer_config(belle_sip_stack_t *stack,const belle_sip_timer_config_t *timer_config){ belle_sip_message("Setting timer config to T1 [%i], T2 [%i], T3 [%i], T4 [%i] on stack [%p]", timer_config->T1 , timer_config->T2 , timer_config->T3 , timer_config->T4 , stack); stack->timer_config=*timer_config; }
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END static belle_sip_socket_t create_udp_socket(const char *addr, int *port, int *family){ struct addrinfo hints={0}; struct addrinfo *res=NULL; int err; belle_sip_socket_t sock; char portnum[10]; int optval=1; if (*port==-1) *port=0; /*random port for bind()*/ snprintf(portnum,sizeof(portnum),"%i",*port); hints.ai_family=AF_UNSPEC; hints.ai_socktype=SOCK_DGRAM; hints.ai_protocol=IPPROTO_UDP; hints.ai_flags=AI_NUMERICSERV; err=getaddrinfo(addr,portnum,&hints,&res); if (err!=0){ belle_sip_error("getaddrinfo() failed for %s port %i: %s",addr,*port,gai_strerror(err)); return -1; } *family=res->ai_family; sock=socket(res->ai_family,res->ai_socktype,res->ai_protocol); if (sock==-1){ belle_sip_error("Cannot create UDP socket: %s",belle_sip_get_socket_error_string()); freeaddrinfo(res); return -1; } err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof (optval)); if (err == -1){ belle_sip_warning ("Fail to set SIP/UDP address reusable: %s.", belle_sip_get_socket_error_string()); } err=bind(sock,res->ai_addr,res->ai_addrlen); if (err==-1){ belle_sip_error("udp bind() failed for %s port %i: %s",addr,*port,belle_sip_get_socket_error_string()); close_socket(sock); freeaddrinfo(res); return -1; } freeaddrinfo(res); if (*port==0){ struct sockaddr_storage saddr; socklen_t saddr_len=sizeof(saddr); err=getsockname(sock,(struct sockaddr*)&saddr,&saddr_len); if (err==0){ err=getnameinfo((struct sockaddr*)&saddr,saddr_len,NULL,0,portnum,sizeof(portnum),NI_NUMERICSERV|NI_NUMERICHOST); if (err==0){ *port=atoi(portnum); belle_sip_message("Random UDP port is %i",*port); }else belle_sip_error("udp bind failed, getnameinfo(): %s",gai_strerror(err)); }else belle_sip_error("udp bind failed, getsockname(): %s",belle_sip_get_socket_error_string()); } return sock; }
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; }
static void http_provider_uninit(belle_http_provider_t *obj){ belle_sip_message("http provider destroyed."); belle_sip_free(obj->bind_ip); belle_sip_list_for_each(obj->tcp_channels,(void (*)(void*))belle_sip_channel_force_close); belle_sip_list_free_with_data(obj->tcp_channels,belle_sip_object_unref); belle_sip_list_for_each(obj->tls_channels,(void (*)(void*))belle_sip_channel_force_close); belle_sip_list_free_with_data(obj->tls_channels,belle_sip_object_unref); belle_sip_object_unref(obj->verify_ctx); }
static void testMalformedFrom_process_response_cb(void *user_ctx, const belle_sip_response_event_t *event){ int status = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)); belle_sip_message("testMalformedFrom_process_response_cb [%i]",status); (*(int*)user_ctx) += 1; // increment the call counter CU_ASSERT( status == 400 ); }
void belle_sip_transaction_set_state(belle_sip_transaction_t *t, belle_sip_transaction_state_t state) { belle_sip_message("Changing [%s] [%s] transaction [%p], from state [%s] to [%s]", BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_client_transaction_t) ? "client" : "server", belle_sip_request_get_method(t->request), t, belle_sip_transaction_state_to_string(t->state), belle_sip_transaction_state_to_string(state)); t->state=state; }