/* this functions runs a simple stun test and return the number of milliseconds to complete the tests, or -1 if the test were failed.*/ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ const char *server=linphone_core_get_stun_server(lc); StunCandidate *ac=&call->ac; StunCandidate *vc=&call->vc; if (lc->sip_conf.ipv6_enabled){ ms_warning("stun support is not implemented for ipv6"); return -1; } if (server!=NULL){ const struct addrinfo *ai=linphone_core_get_stun_server_addrinfo(lc); ortp_socket_t sock1=-1, sock2=-1; int loops=0; bool_t video_enabled=linphone_core_video_enabled(lc); bool_t got_audio,got_video; bool_t cone_audio=FALSE,cone_video=FALSE; struct timeval init,cur; double elapsed; int ret=0; if (ai==NULL){ ms_error("Could not obtain stun server addrinfo."); return -1; } if (lc->vtable.display_status!=NULL) lc->vtable.display_status(lc,_("Stun lookup in progress...")); /*create the two audio and video RTP sockets, and send STUN message to our stun server */ sock1=create_socket(call->audio_port); if (sock1==-1) return -1; if (video_enabled){ sock2=create_socket(call->video_port); if (sock2==-1) return -1; } got_audio=FALSE; got_video=FALSE; ortp_gettimeofday(&init,NULL); do{ int id; if (loops%20==0){ ms_message("Sending stun requests..."); sendStunRequest(sock1,ai->ai_addr,ai->ai_addrlen,11,TRUE); sendStunRequest(sock1,ai->ai_addr,ai->ai_addrlen,1,FALSE); if (sock2!=-1){ sendStunRequest(sock2,ai->ai_addr,ai->ai_addrlen,22,TRUE); sendStunRequest(sock2,ai->ai_addr,ai->ai_addrlen,2,FALSE); } } ms_usleep(10000); if (recvStunResponse(sock1,ac->addr, &ac->port,&id)>0){ ms_message("STUN test result: local audio port maps to %s:%i", ac->addr, ac->port); if (id==11) cone_audio=TRUE; got_audio=TRUE; } if (recvStunResponse(sock2,vc->addr, &vc->port,&id)>0){ ms_message("STUN test result: local video port maps to %s:%i", vc->addr, vc->port); if (id==22) cone_video=TRUE; got_video=TRUE; } ortp_gettimeofday(&cur,NULL); elapsed=((cur.tv_sec-init.tv_sec)*1000.0) + ((cur.tv_usec-init.tv_usec)/1000.0); if (elapsed>2000) { ms_message("Stun responses timeout, going ahead."); ret=-1; break; } loops++; }while(!(got_audio && (got_video||sock2==-1) ) ); if (ret==0) ret=(int)elapsed; if (!got_audio){ ms_error("No stun server response for audio port."); }else{ if (!cone_audio) { ms_message("NAT is symmetric for audio port"); } } if (sock2!=-1){ if (!got_video){ ms_error("No stun server response for video port."); }else{ if (!cone_video) { ms_message("NAT is symmetric for video port."); } } } close_socket(sock1); if (sock2!=-1) close_socket(sock2); return ret; } return -1; }
void sal_use_101(Sal *ctx, bool_t use_101){ ms_warning("sal_use_101 is deprecated"); return ; }
static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, belle_sdp_media_description_t *media_desc) { SalStreamDescription *stream; belle_sdp_connection_t* cnx; belle_sdp_media_t* media; belle_sdp_attribute_t* attribute; const char* value; const char *mtype,*proto; stream=&md->streams[md->nb_streams]; media=belle_sdp_media_description_get_media ( media_desc ); proto = belle_sdp_media_get_protocol ( media ); stream->proto=SalProtoOther; if ( proto ) { if (strcasecmp(proto, "RTP/AVP") == 0) { stream->proto = SalProtoRtpAvp; } else if (strcasecmp(proto, "RTP/SAVP") == 0) { stream->proto = SalProtoRtpSavp; } else if (strcasecmp(proto, "RTP/AVPF") == 0) { stream->proto = SalProtoRtpAvpf; } else if (strcasecmp(proto, "RTP/SAVPF") == 0) { stream->proto = SalProtoRtpSavpf; } else if (strcasecmp(proto, "UDP/TLS/RTP/SAVP") == 0) { stream->proto = SalProtoUdpTlsRtpSavp; } else if (strcasecmp(proto, "UDP/TLS/RTP/SAVPF") == 0) { stream->proto = SalProtoUdpTlsRtpSavpf; } else { strncpy(stream->proto_other,proto,sizeof(stream->proto_other)-1); } } if ( ( cnx=belle_sdp_media_description_get_connection ( media_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) { strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ), sizeof ( stream->rtp_addr ) -1 ); stream->ttl=belle_sdp_connection_get_ttl(cnx); } stream->rtp_port=belle_sdp_media_get_media_port ( media ); mtype = belle_sdp_media_get_media_type ( media ); if ( strcasecmp ( "audio", mtype ) == 0 ) { stream->type=SalAudio; } else if ( strcasecmp ( "video", mtype ) == 0 ) { stream->type=SalVideo; } else { stream->type=SalOther; strncpy ( stream->typeother,mtype,sizeof ( stream->typeother )-1 ); } if ( belle_sdp_media_description_get_bandwidth ( media_desc,"AS" ) >0 ) { stream->bandwidth=belle_sdp_media_description_get_bandwidth ( media_desc,"AS" ); } if ( belle_sdp_media_description_get_attribute ( media_desc,"sendrecv" ) ) { stream->dir=SalStreamSendRecv; } else if ( belle_sdp_media_description_get_attribute ( media_desc,"sendonly" ) ) { stream->dir=SalStreamSendOnly; } else if ( belle_sdp_media_description_get_attribute ( media_desc,"recvonly" ) ) { stream->dir=SalStreamRecvOnly; } else if ( belle_sdp_media_description_get_attribute ( media_desc,"inactive" ) ) { stream->dir=SalStreamInactive; } else { stream->dir=md->dir; /*takes default value if not present*/ } /* Get media payload types */ sdp_parse_payload_types(media_desc, stream); /* Get media specific RTCP attribute */ stream->rtcp_port = stream->rtp_port + 1; snprintf(stream->rtcp_addr, sizeof(stream->rtcp_addr), "%s", stream->rtp_addr); attribute=belle_sdp_media_description_get_attribute(media_desc,"rtcp"); if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){ char tmp[256]; int nb = sscanf(value, "%d IN IP4 %s", &stream->rtcp_port, tmp); if (nb == 1) { /* SDP rtcp attribute only contains the port */ } else if (nb == 2) { strncpy(stream->rtcp_addr, tmp, sizeof(stream->rtcp_addr)-1); } else { ms_warning("sdp has a strange a=rtcp line (%s) nb=%i", value, nb); } } /* Read DTLS specific attributes : check is some are found in the stream description otherwise copy the session description one(which are at least set to Invalid) */ if (((stream->proto == SalProtoUdpTlsRtpSavpf) || (stream->proto == SalProtoUdpTlsRtpSavp))) { attribute=belle_sdp_media_description_get_attribute(media_desc,"setup"); if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){ if (strncmp(value, "actpass", 7) == 0) { stream->dtls_role = SalDtlsRoleUnset; } else if (strncmp(value, "active", 6) == 0) { stream->dtls_role = SalDtlsRoleIsClient; } else if (strncmp(value, "passive", 7) == 0) { stream->dtls_role = SalDtlsRoleIsServer; } } if (stream->dtls_role != SalDtlsRoleInvalid && (attribute=belle_sdp_media_description_get_attribute(media_desc,"fingerprint"))) { strncpy(stream->dtls_fingerprint, belle_sdp_attribute_get_value(attribute),sizeof(stream->dtls_fingerprint)); } } /* Read crypto lines if any */ if ((stream->proto == SalProtoRtpSavpf) || (stream->proto == SalProtoRtpSavp)) { sdp_parse_media_crypto_parameters(media_desc, stream); } /* Get ICE candidate attributes if any */ sdp_parse_media_ice_parameters(media_desc, stream); /* Get RTCP-FB attributes if any */ if ((stream->proto == SalProtoRtpAvpf) || (stream->proto == SalProtoRtpSavpf)) { enable_avpf_for_stream(stream); sdp_parse_rtcp_fb_parameters(media_desc, stream); } /* Get RTCP-XR attributes if any */ stream->rtcp_xr = md->rtcp_xr; // Use session parameters if no stream parameters are defined sdp_parse_media_rtcp_xr_parameters(media_desc, &stream->rtcp_xr); md->nb_streams++; return stream; }
static void unimplemented_stub(){ ms_warning("Unimplemented SAL callback"); }
void sal_use_double_registrations(Sal *ctx, bool_t enabled){ ms_warning("sal_use_double_registrations is deprecated"); return ; }
static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details, int code){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); char *msg486=_("User is busy."); char *msg480=_("User is temporarily unavailable."); /*char *retrymsg=_("%s. Retry after %i minute(s).");*/ char *msg600=_("User does not want to be disturbed."); char *msg603=_("Call declined."); const char *msg=details; LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); LinphoneCall *referer=call->referer; if (call==NULL){ ms_warning("Call faillure reported on already terminated call."); return ; } if (lc->vtable.show) lc->vtable.show(lc); if (error==SalErrorNoResponse){ msg=_("No response."); if (lc->vtable.display_status) lc->vtable.display_status(lc,msg); }else if (error==SalErrorProtocol){ msg=details ? details : _("Protocol error."); if (lc->vtable.display_status) lc->vtable.display_status(lc, msg); }else if (error==SalErrorFailure){ switch(sr){ case SalReasonDeclined: msg=msg603; if (lc->vtable.display_status) lc->vtable.display_status(lc,msg603); break; case SalReasonBusy: msg=msg486; if (lc->vtable.display_status) lc->vtable.display_status(lc,msg486); break; case SalReasonRedirect: { ms_error("case SalReasonRedirect"); linphone_call_stop_media_streams(call); if ( call->state==LinphoneCallOutgoingInit || call->state==LinphoneCallOutgoingProgress || call->state==LinphoneCallOutgoingRinging /*push case*/ || call->state==LinphoneCallOutgoingEarlyMedia){ LinphoneAddress* redirection_to = (LinphoneAddress*)sal_op_get_remote_contact_address(call->op); if( redirection_to ){ char* url = linphone_address_as_string(redirection_to); ms_error("Redirecting call [%p] to %s",call, url); ms_free(url); linphone_call_create_op(call); linphone_core_start_invite(lc, call, redirection_to); return; } } msg=_("Redirected"); if (lc->vtable.display_status) lc->vtable.display_status(lc,msg); } break; case SalReasonTemporarilyUnavailable: msg=msg480; if (lc->vtable.display_status) lc->vtable.display_status(lc,msg480); break; case SalReasonNotFound: if (lc->vtable.display_status) lc->vtable.display_status(lc,msg); break; case SalReasonDoNotDisturb: msg=msg600; if (lc->vtable.display_status) lc->vtable.display_status(lc,msg600); break; case SalReasonUnsupportedContent: /*<this is for compatibility: linphone sent 415 because of SDP offer answer failure*/ case SalReasonNotAcceptable: //media_encryption_mandatory if (call->params.media_encryption == LinphoneMediaEncryptionSRTP && !linphone_core_is_media_encryption_mandatory(lc)) { int i; ms_message("Outgoing call [%p] failed with SRTP (SAVP) enabled",call); linphone_call_stop_media_streams(call); if ( call->state==LinphoneCallOutgoingInit || call->state==LinphoneCallOutgoingProgress || call->state==LinphoneCallOutgoingRinging /*push case*/ || call->state==LinphoneCallOutgoingEarlyMedia){ ms_message("Retrying call [%p] with AVP",call); /* clear SRTP local params */ call->params.media_encryption = LinphoneMediaEncryptionNone; for(i=0; i<call->localdesc->n_active_streams; i++) { call->localdesc->streams[i].proto = SalProtoRtpAvp; memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto)); } linphone_core_restart_invite(lc, call); return; } } msg=_("Incompatible media parameters."); if (lc->vtable.display_status) lc->vtable.display_status(lc,msg); break; case SalReasonRequestPending: /*restore previous state, the application will decide to resubmit the action if relevant*/ call->reason=linphone_reason_from_sal(sr); linphone_call_set_state(call,call->prevstate,msg); return; break; default: if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Call failed.")); } } /*some call error are not fatal*/ switch (call->state) { case LinphoneCallUpdating: case LinphoneCallPausing: case LinphoneCallResuming: ms_message("Call error on state [%s], restoring previous state",linphone_call_state_to_string(call->prevstate)); call->reason=linphone_reason_from_sal(sr); linphone_call_set_state(call, call->prevstate,details); return; default: break; /*nothing to do*/ } linphone_core_stop_ringing(lc); linphone_call_stop_media_streams(call); #ifdef BUILD_UPNP linphone_call_delete_upnp_session(call); #endif //BUILD_UPNP call->reason=linphone_reason_from_sal(sr); if (sr==SalReasonDeclined){ linphone_call_set_state(call,LinphoneCallEnd,"Call declined."); }else{ linphone_call_set_state(call,LinphoneCallError,details); if (sr==SalReasonBusy) linphone_core_play_named_tone(lc,LinphoneToneBusy); } if (referer){ /*notify referer of the failure*/ linphone_core_notify_refer_state(lc,referer,call); /*schedule automatic resume of the call. This must be done only after the notifications are completed due to dialog serialization of requests.*/ linphone_core_queue_task(lc,(belle_sip_source_func_t)resume_call_after_failed_transfer,linphone_call_ref(referer),"Automatic call resuming after failed transfer"); } }
static void process_request_event(void *sal, const belle_sip_request_event_t *event) { SalOp* op=NULL; belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event); belle_sip_header_address_t* origin_address; belle_sip_header_address_t* address; belle_sip_header_from_t* from_header; belle_sip_header_to_t* to; belle_sip_response_t* resp; belle_sip_header_t *evh; const char *method=belle_sip_request_get_method(req); from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); if (dialog) { op=(SalOp*)belle_sip_dialog_get_application_data(dialog); if (op==NULL || op->state==SalOpStateTerminated){ ms_warning("Receiving request for null or terminated op [%p], ignored",op); return; } }else if (strcmp("INVITE",method)==0) { op=sal_op_new((Sal*)sal); op->dir=SalOpDirIncoming; sal_op_call_fill_cbs(op); }else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { op=sal_op_new((Sal*)sal); op->dir=SalOpDirIncoming; if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){ sal_op_presence_fill_cbs(op); }else sal_op_subscribe_fill_cbs(op); }else if (strcmp("MESSAGE",method)==0) { op=sal_op_new((Sal*)sal); op->dir=SalOpDirIncoming; sal_op_message_fill_cbs(op); }else if (strcmp("OPTIONS",method)==0) { resp=belle_sip_response_create_from_request(req,200); belle_sip_provider_send_response(((Sal*)sal)->prov,resp); return; }else if (strcmp("INFO",method)==0) { resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/ belle_sip_provider_send_response(((Sal*)sal)->prov,resp); return; }else if (strcmp("BYE",method)==0) { resp=belle_sip_response_create_from_request(req,481);/*out of dialog BYE */ belle_sip_provider_send_response(((Sal*)sal)->prov,resp); return; }else { ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); resp=belle_sip_response_create_from_request(req,501); belle_sip_provider_send_response(((Sal*)sal)->prov,resp); return; } if (!op->base.from_address) { address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); sal_op_set_from_address(op,(SalAddress*)address); belle_sip_object_unref(address); } if (!op->base.to_address) { to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t); address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))); sal_op_set_to_address(op,(SalAddress*)address); belle_sip_object_unref(address); } if (!op->base.origin) { /*set origin uri*/ origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req)); __sal_op_set_network_origin_address(op,(SalAddress*)origin_address); belle_sip_object_unref(origin_address); } if (!op->base.remote_ua) { sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(req)); } if (!op->base.call_id) { op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_call_id_t)))); } /*It is worth noting that proxies can (and will) remove this header field*/ sal_op_set_privacy_from_message(op,(belle_sip_message_t*)req); sal_op_assign_recv_headers(op,(belle_sip_message_t*)req); if (op->callbacks.process_request_event) { op->callbacks.process_request_event(op,event); } else { ms_error("sal process_request_event not implemented yet"); } }
static void full_tunnel_video_ice_call(void){ if (linphone_core_tunnel_available()){ call_with_tunnel_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionNone, TRUE); }else ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__); }
static void tunnel_ice_call(void) { if (linphone_core_tunnel_available()) call_base(LinphoneMediaEncryptionNone,FALSE,FALSE,LinphonePolicyUseIce,TRUE); else ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__); }
static void * winsnd_thread(void *p){ MSSndCard *card=(MSSndCard*)p; WinSndData *d=(WinSndData*)card->data; int bsize=d->rate/8000 * 320; uint8_t *rtmpbuff=NULL; uint8_t *wtmpbuff=NULL; int err; MMRESULT mr = NOERROR; int pos_whdr=0; d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; d->sound_err=winsnd_open(d, d->devid, d->bits,d->stereo,d->rate,&bsize); if (d->sound_err==0){ rtmpbuff=(uint8_t*)alloca(bsize); wtmpbuff=(uint8_t*)alloca(bsize); } while(d->read_started || d->write_started){ if (d->sound_err==0){ if (d->write_started){ #if 0 if (d->stat_output>0 && d->buffer_playing==0) { ms_error("No data currently playing in sound card" ); } if (d->stat_output>0 && (d->stat_input-d->stat_output>10 || d->stat_input-d->stat_output<-10)) ms_error("Not perfectly synchronized (input-output=%i)", d->stat_input-d->stat_output); #endif while (d->buffer_playing<6 && d->buffer_playing<MAX_WAVEHDR) { ms_mutex_lock(&d->mutex); err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); ms_mutex_unlock(&d->mutex); if (err!=bsize) break; ms_mutex_lock(&d->mutex); /* write to sound devide! */ memcpy (d->waveouthdr[pos_whdr].lpData, wtmpbuff, bsize); mr = waveOutWrite (d->waveoutdev, &(d->waveouthdr[pos_whdr]), sizeof (d->waveouthdr[pos_whdr])); if (mr != MMSYSERR_NOERROR) { if (mr == WAVERR_STILLPLAYING) { /* retry later */ /* data should go back to queue */ /* TODO */ ms_warning("sound device write STILL_PLAYING (waveOutWrite:0x%i)", mr); } else { ms_warning("sound device write returned (waveOutWrite:0x%i)", mr); } } else { d->buffer_playing++; pos_whdr++; if (pos_whdr == MAX_WAVEHDR) pos_whdr = 0; /* loop over the prepared blocks */ } ms_mutex_unlock(&d->mutex); if (err<0){ #if !defined(_WIN32_WCE) ms_warning("Fail to write %i bytes from soundcard: %s", bsize,strerror(errno)); #else ms_warning("Fail to write %i bytes from soundcard: %i", bsize,WSAGetLastError()); #endif } } if (d->buffer_playing==6 || d->buffer_playing==MAX_WAVEHDR) { int discarded=0; ms_mutex_lock(&d->mutex); while (d->bufferizer->size>=bsize){ discarded++; d->stat_notplayed++; err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); } ms_mutex_unlock(&d->mutex); if (discarded>0) ms_error("Extra data for sound card removed (%ims), (playing: %i) (input-output: %i)", (discarded*20*320)/320, d->buffer_playing, d->stat_input - d->stat_output); } #if !defined(_WIN32_WCE) Sleep(5); #endif #if defined(_WIN32_WCE) Sleep(10); #endif }else { int discarded=0; /* don't think this is usefull, anyway... */ ms_mutex_lock(&d->mutex); while (d->bufferizer->size>=bsize){ discarded++; err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); } ms_mutex_unlock(&d->mutex); if (discarded>0) ms_error("Extra data for sound card removed (%ims), (playing: %i) (input-output: %i)", (discarded*20)/320, d->buffer_playing, d->stat_input - d->stat_output); Sleep(10); } }else Sleep(10); } if (d->sound_err==0) { int i; int count=0; /* close sound card */ ms_error("Shutting down sound device (playing: %i) (input-output: %i) (notplayed: %i)", d->buffer_playing, d->stat_input - d->stat_output, d->stat_notplayed); /* unprepare buffer */ for (i = 0; i < MAX_WAVEHDR; i++) { int counttry=0; for (counttry=0;counttry<10;counttry++) { mr = waveInUnprepareHeader (d->waveindev, &(d->waveinhdr[i]), sizeof (d->waveinhdr[i])); if (mr != MMSYSERR_NOERROR) { ms_error("Failed to unprepared %i buffer from sound card (waveInUnprepareHeader:0x%i", count, mr); Sleep (20); } else { count++; ms_message("successfully unprepared %i buffer from sound card.", count); break; } } } ms_warning("unprepared %i buffer from sound card.", count); mr = waveInStop (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_error("failed to stop recording sound card (waveInStop:0x%i)", mr); } else { ms_message("successfully stopped recording sound card"); } mr = waveInReset (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_warning("failed to reset recording sound card (waveInReset:0x%i)", mr); } else { ms_message("successful reset of recording sound card"); } mr = waveInClose (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_warning("failed to close recording sound card (waveInClose:0x%i)", mr); } else { ms_message("successfully closed recording sound card"); } d->sound_err=-1; } d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; return NULL; }
static void size_conv_process(MSFilter *f){ SizeConvState *s=(SizeConvState*)f->data; YuvBuf inbuf; mblk_t *im; int cur_frame; ms_filter_lock(f); if (s->frame_count==-1){ s->start_time=(float)f->ticker->time; s->frame_count=0; } while((im=ms_queue_get(f->inputs[0]))!=NULL ){ putq(&s->rq, im); } cur_frame=(int)((f->ticker->time-s->start_time)*s->fps/1000.0); if (cur_frame<=s->frame_count && s->fps>=0) { /* too much frame */ while(s->rq.q_mcount>1){ ms_message("MSSizeConv: extra frame removed."); im=getq(&s->rq); freemsg(im); } ms_filter_unlock(f); return; } if (cur_frame>s->frame_count && s->fps>=0) { /*keep the most recent frame if several frames have been captured */ while(s->rq.q_mcount>1){ ms_message("MSSizeConv: extra frame removed."); im=getq(&s->rq); freemsg(im); } } while((im=getq(&s->rq))!=NULL ){ if (ms_yuv_buf_init_from_mblk(&inbuf,im)==0){ if (inbuf.w==s->target_vsize.width && inbuf.h==s->target_vsize.height){ ms_queue_put(f->outputs[0],im); }else{ MSScalerContext *sws_ctx=get_resampler(s,inbuf.w,inbuf.h); mblk_t *om=size_conv_alloc_mblk(s); if (ms_scaler_process(sws_ctx,inbuf.planes,inbuf.strides,s->outbuf.planes, s->outbuf.strides)<0){ ms_error("MSSizeConv: error in ms_scaler_process()."); freemsg(om); }else{ ms_queue_put(f->outputs[0],om); } freemsg(im); } s->frame_count++; }else{ ms_warning("size_conv_process(): bad buffer."); freemsg(im); } } ms_filter_unlock(f); }
static int winsnd_open(WinSndData *device, int devnumber, int bits,int stereo, int rate, int *minsz) { MMRESULT mr = NOERROR; DWORD dwFlag; int i; int channel = 1; if (stereo>0) channel = stereo; device->wfx.wFormatTag = WAVE_FORMAT_PCM; device->wfx.cbSize = 0; device->wfx.nAvgBytesPerSec = 16000; device->wfx.nBlockAlign = 2; device->wfx.nChannels = channel; device->wfx.nSamplesPerSec = rate; /* 8000; */ device->wfx.wBitsPerSample = bits; dwFlag = CALLBACK_FUNCTION; if (devnumber != WAVE_MAPPER) dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION; mr = waveOutOpen (&(device->waveoutdev), devnumber, &(device->wfx), (DWORD) SpeakerCallback, (DWORD)device, dwFlag); if (mr != NOERROR) { ms_warning("Failed to open device: trying default device. (waveOutOpen:0x%i)", mr); dwFlag = CALLBACK_FUNCTION; mr = waveOutOpen (&(device->waveoutdev), WAVE_MAPPER, &(device->wfx), (DWORD) SpeakerCallback, (DWORD)device, dwFlag); } if (mr != NOERROR) { ms_warning("Failed to open windows sound device. (waveOutOpen:0x%i)", mr); return -1; } #if 0 #define MM_WOM_SETSECONDARYGAINCLASS (WM_USER) #define MM_WOM_SETSECONDARYGAINLIMIT (WM_USER+1) #define MM_WOM_FORCESPEAKER (WM_USER+2) bool bSpeaker=TRUE; mr = waveOutMessage(device->waveoutdev, MM_WOM_FORCESPEAKER, bSpeaker, 0); if (mr != NOERROR) { ms_warning("Failed to use earphone. (waveOutMessage:0x%i)", mr); return -1; } typedef HRESULT (* _SetSpeakerMode)(DWORD mode); _SetSpeakerMode pfnSetSpeakerMode; HINSTANCE hDll = LoadLibrary(L"\\windows\\ossvcs.dll"); //_debug(L"ossvcs.dll h=%X",hDll); pfnSetSpeakerMode = (_SetSpeakerMode)GetProcAddress(hDll,(LPCTSTR)218); if (pfnSetSpeakerMode) { //_debug(L"SetSpeakerMode imported."); DWORD sm = 0; //_debug(L"SpeakerMode set to %d", sm); pfnSetSpeakerMode(sm); } //else //_debug(L"pfnSetSpeakerMode import failed."); FreeLibrary(hDll); #endif #ifdef CONTROLVOLUME mr = waveOutGetVolume(device->waveoutdev, &device->dwOldVolume); if (mr != NOERROR) { ms_warning("Failed to get volume device. (waveOutGetVolume:0x%i)", mr); } mr = waveOutSetVolume(device->waveoutdev, 0xFFFFFFFF); if (mr != NOERROR) { ms_warning("Failed to set volume device. (waveOutSetVolume:0x%i)", mr); } #endif /* prepare windows buffers */ for (i = 0; i < MAX_WAVEHDR; i++) { memset (&(device->waveouthdr[i]), 0, sizeof (device->waveouthdr[i])); device->waveouthdr[i].lpData = device->waveoutbuffer[i]; /* BUG: on ne connait pas la taille des frames a recevoir... on utilise enc_frame_per_packet au lien de dec_frame_per_packet */ device->waveouthdr[i].dwBufferLength = device->rate/8000 * WINSND_BUFLEN; /* 480 pour 98 (speex) */ device->waveouthdr[i].dwFlags = 0; device->waveouthdr[i].dwUser = i; mr = waveOutPrepareHeader (device->waveoutdev, &(device->waveouthdr[i]), sizeof (device->waveouthdr[i])); if (mr != MMSYSERR_NOERROR){ ms_warning("Failed to prepare windows sound device. (waveOutPrepareHeader:0x%i)", mr); } else { ms_message("Sound Header prepared %i for windows sound device. (waveOutPrepareHeader)", i); } } /* Init Microphone device */ dwFlag = CALLBACK_FUNCTION; if (devnumber != WAVE_MAPPER) dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION; mr = waveInOpen (&(device->waveindev), devnumber, &(device->wfx), (DWORD) WaveInCallback, (DWORD)device, dwFlag); if (mr != NOERROR) { ms_warning("Failed to open device: trying default device. (waveInOpen:0x%i)", mr); dwFlag = CALLBACK_FUNCTION; mr = waveInOpen (&(device->waveindev), WAVE_MAPPER, &(device->wfx), (DWORD) WaveInCallback, (DWORD)device, dwFlag); } if (mr != NOERROR) { ms_warning("Failed to prepare windows sound device. (waveInOpen:0x%i)", mr); return -1; } for (i = 0; i < MAX_WAVEHDR; i++) { memset (&(device->waveinhdr[i]), 0, sizeof (device->waveinhdr[i])); device->waveinhdr[i].lpData = device->waveinbuffer[i]; /* frameSize */ device->waveinhdr[i].dwBufferLength = device->rate/8000 * WINSND_BUFLEN; device->waveinhdr[i].dwFlags = 0; device->waveinhdr[i].dwUser = i; mr = waveInPrepareHeader (device->waveindev, &(device->waveinhdr[i]), sizeof (device->waveinhdr[i])); if (mr == MMSYSERR_NOERROR){ mr = waveInAddBuffer (device->waveindev, &(device->waveinhdr[i]), sizeof (device->waveinhdr[i])); if (mr == MMSYSERR_NOERROR) { ms_message("Sound Header prepared %i for windows sound device. (waveInAddBuffer)", i); } else { ms_warning("Failed to prepare windows sound device. (waveInAddBuffer:0x%i)", mr); } } else { ms_warning("Failed to prepare windows sound device. (waveInPrepareHeader:0x%i)", mr); } } #ifndef DISABLE_SPEEX #if 0 device->pst = speex_preprocess_state_init((device->rate/8000 * 320)/2, device->rate); if (device->pst!=NULL) { float f; i=1; speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_VAD, &i); i=1; speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DENOISE, &i); i=0; speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_AGC, &i); f=8000; speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f); i=0; speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB, &i); f=.4; speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f); f=.3; speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f); } #endif #endif mr = waveInStart (device->waveindev); if (mr != MMSYSERR_NOERROR) { ms_warning("Failed to start recording on windows sound device. (waveInStart:0x%i)", mr); return -1; } *minsz=device->rate/8000 * 320; return 0; }
static void CALLBACK WaveInCallback (HWAVEIN waveindev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { WAVEHDR *wHdr; MMRESULT mr = NOERROR; WinSndData *device; device = (WinSndData *)dwInstance; switch (uMsg) { case MM_WOM_DONE: wHdr = (WAVEHDR *) dwParam1; /* A waveform-audio data block has been played and can now be freed. */ ms_message("WaveInCallback : MM_WOM_DONE"); waveInUnprepareHeader (waveindev, (LPWAVEHDR) wHdr, sizeof (WAVEHDR)); break; case WIM_OPEN: ms_message("WaveInCallback : WIM_OPEN"); break; case WIM_CLOSE: ms_message("WaveInCallback : WIM_CLOSE"); break; case WIM_DATA: wHdr = (WAVEHDR *) dwParam1; device->bytes_read+=wHdr->dwBytesRecorded; if (!device->read_started && !device->write_started) { mr = waveInUnprepareHeader (device->waveindev, (LPWAVEHDR) wHdr, sizeof (WAVEHDR)); ms_warning("WaveInCallback : unprepare header (waveInUnprepareHeader:0x%i)", mr); return; } if (wHdr->dwBufferLength!=wHdr->dwBytesRecorded) { mr = waveInAddBuffer (device->waveindev, wHdr, sizeof (device->waveinhdr[wHdr->dwUser])); if (mr != MMSYSERR_NOERROR) { ms_warning("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr); } return; } ms_mutex_lock(&device->mutex); if (device->read_started) { mblk_t *rm=NULL; if (rm==NULL) rm=allocb(wHdr->dwBufferLength,0); memcpy(rm->b_wptr,wHdr->lpData, wHdr->dwBufferLength); #ifndef DISABLE_SPEEX if (device->pst!=NULL) { int vad; //memset(rm->b_wptr,0, wHdr->dwBufferLength); vad = speex_preprocess(device->pst, (short*)rm->b_wptr, NULL); #if 0 if (vad!=1) ms_message("WaveInCallback : %d", vad); #endif } #endif rm->b_wptr+=wHdr->dwBufferLength; putq(&device->rq,rm); device->stat_input++; rm=NULL; } ms_mutex_unlock(&device->mutex); mr = waveInAddBuffer (device->waveindev, wHdr, sizeof (device->waveinhdr[wHdr->dwUser])); if (mr != MMSYSERR_NOERROR) { ms_warning("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr); return; } } }
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session) { const char *rtp_addr, *rtcp_addr; IceSessionState session_state = ice_session_state(session); int nb_candidates; int i, j; bool_t result; if (session_state == IS_Completed) { desc->ice_completed = TRUE; result = ice_check_list_selected_valid_local_candidate(ice_session_check_list(session, 0), &rtp_addr, NULL, NULL, NULL); if (result == TRUE) { strncpy(desc->addr, rtp_addr, sizeof(desc->addr)); } else { ms_warning("If ICE has completed successfully, rtp_addr should be set!"); } } else { desc->ice_completed = FALSE; } strncpy(desc->ice_pwd, ice_session_local_pwd(session), sizeof(desc->ice_pwd)); strncpy(desc->ice_ufrag, ice_session_local_ufrag(session), sizeof(desc->ice_ufrag)); for (i = 0; i < desc->n_active_streams; i++) { SalStreamDescription *stream = &desc->streams[i]; IceCheckList *cl = ice_session_check_list(session, i); nb_candidates = 0; if (cl == NULL) continue; if (ice_check_list_state(cl) == ICL_Completed) { stream->ice_completed = TRUE; result = ice_check_list_selected_valid_local_candidate(ice_session_check_list(session, i), &rtp_addr, &stream->rtp_port, &rtcp_addr, &stream->rtcp_port); } else { stream->ice_completed = FALSE; result = ice_check_list_default_local_candidate(ice_session_check_list(session, i), &rtp_addr, &stream->rtp_port, &rtcp_addr, &stream->rtcp_port); } if (result == TRUE) { strncpy(stream->rtp_addr, rtp_addr, sizeof(stream->rtp_addr)); strncpy(stream->rtcp_addr, rtcp_addr, sizeof(stream->rtcp_addr)); } else { memset(stream->rtp_addr, 0, sizeof(stream->rtp_addr)); memset(stream->rtcp_addr, 0, sizeof(stream->rtcp_addr)); } if ((strlen(ice_check_list_local_pwd(cl)) != strlen(desc->ice_pwd)) || (strcmp(ice_check_list_local_pwd(cl), desc->ice_pwd))) strncpy(stream->ice_pwd, ice_check_list_local_pwd(cl), sizeof(stream->ice_pwd)); else memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd)); if ((strlen(ice_check_list_local_ufrag(cl)) != strlen(desc->ice_ufrag)) || (strcmp(ice_check_list_local_ufrag(cl), desc->ice_ufrag))) strncpy(stream->ice_ufrag, ice_check_list_local_ufrag(cl), sizeof(stream->ice_ufrag)); else memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd)); stream->ice_mismatch = ice_check_list_is_mismatch(cl); if ((ice_check_list_state(cl) == ICL_Running) || (ice_check_list_state(cl) == ICL_Completed)) { memset(stream->ice_candidates, 0, sizeof(stream->ice_candidates)); for (j = 0; j < MIN(ms_list_size(cl->local_candidates), SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES); j++) { SalIceCandidate *sal_candidate = &stream->ice_candidates[nb_candidates]; IceCandidate *ice_candidate = ms_list_nth_data(cl->local_candidates, j); const char *default_addr = NULL; int default_port = 0; if (ice_candidate->componentID == 1) { default_addr = stream->rtp_addr; default_port = stream->rtp_port; } else if (ice_candidate->componentID == 2) { default_addr = stream->rtcp_addr; default_port = stream->rtcp_port; } else continue; if (default_addr[0] == '\0') default_addr = desc->addr; /* Only include the candidates matching the default destination for each component of the stream if the state is Completed as specified in RFC5245 section 9.1.2.2. */ if ((ice_check_list_state(cl) == ICL_Completed) && !((ice_candidate->taddr.port == default_port) && (strlen(ice_candidate->taddr.ip) == strlen(default_addr)) && (strcmp(ice_candidate->taddr.ip, default_addr) == 0))) continue; strncpy(sal_candidate->foundation, ice_candidate->foundation, sizeof(sal_candidate->foundation)); sal_candidate->componentID = ice_candidate->componentID; sal_candidate->priority = ice_candidate->priority; strncpy(sal_candidate->type, ice_candidate_type(ice_candidate), sizeof(sal_candidate->type)); strncpy(sal_candidate->addr, ice_candidate->taddr.ip, sizeof(sal_candidate->addr)); sal_candidate->port = ice_candidate->taddr.port; if ((ice_candidate->base != NULL) && (ice_candidate->base != ice_candidate)) { strncpy(sal_candidate->raddr, ice_candidate->base->taddr.ip, sizeof(sal_candidate->raddr)); sal_candidate->rport = ice_candidate->base->taddr.port; } nb_candidates++; } } if ((ice_check_list_state(cl) == ICL_Completed) && (ice_session_role(session) == IR_Controlling)) { int rtp_port, rtcp_port; memset(stream->ice_remote_candidates, 0, sizeof(stream->ice_remote_candidates)); if (ice_check_list_selected_valid_remote_candidate(cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port) == TRUE) { strncpy(stream->ice_remote_candidates[0].addr, rtp_addr, sizeof(stream->ice_remote_candidates[0].addr)); stream->ice_remote_candidates[0].port = rtp_port; strncpy(stream->ice_remote_candidates[1].addr, rtcp_addr, sizeof(stream->ice_remote_candidates[1].addr)); stream->ice_remote_candidates[1].port = rtcp_port; } else { ms_error("ice: Selected valid remote candidates should be present if the check list is in the Completed state"); } } else { for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) { stream->ice_remote_candidates[j].addr[0] = '\0'; stream->ice_remote_candidates[j].port = 0; } } } }
static void call_received(SalOp *h){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); LinphoneCall *call; const char *from,*to; char *alt_contact; LinphoneAddress *from_addr, *to_addr; bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",TRUE); /* first check if we can answer successfully to this invite */ if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) { LinphonePresenceActivity *activity = linphone_presence_model_get_activity(lc->presence_model); switch (linphone_presence_activity_get_type(activity)) { case LinphonePresenceActivityBusy: sal_call_decline(h,SalReasonBusy,NULL); break; case LinphonePresenceActivityAppointment: case LinphonePresenceActivityMeeting: case LinphonePresenceActivityOffline: case LinphonePresenceActivityWorship: sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL); break; case LinphonePresenceActivityPermanentAbsence: alt_contact = linphone_presence_model_get_contact(lc->presence_model); if (alt_contact != NULL) { sal_call_decline(h,SalReasonRedirect,alt_contact); ms_free(alt_contact); } break; default: break; } sal_op_release(h); return; } if (!linphone_core_can_we_add_call(lc)){/*busy*/ sal_call_decline(h,SalReasonBusy,NULL); sal_op_release(h); return; } from=sal_op_get_from(h); to=sal_op_get_to(h); from_addr=linphone_address_new(from); to_addr=linphone_address_new(to); if ((already_a_call_with_remote_address(lc,from_addr) && prevent_colliding_calls) || already_a_call_pending(lc)){ ms_warning("Receiving another call while one is ringing or initiated, refusing this one with busy message."); sal_call_decline(h,SalReasonBusy,NULL); sal_op_release(h); linphone_address_destroy(from_addr); linphone_address_destroy(to_addr); return; } call=linphone_call_new_incoming(lc,from_addr,to_addr,h); /* the call is acceptable so we can now add it to our list */ linphone_core_add_call(lc,call); linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */ if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) { /* Defer ringing until the end of the ICE candidates gathering process. */ ms_message("Defer ringing to gather ICE candidates"); return; } #ifdef BUILD_UPNP if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) && (call->upnp_session != NULL)) { /* Defer ringing until the end of the ICE candidates gathering process. */ ms_message("Defer ringing to gather uPnP candidates"); return; } #endif //BUILD_UPNP linphone_core_notify_incoming_call(lc,call); }
static void call_with_tunnel_base(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption, bool_t with_video_and_ice) { if (linphone_core_tunnel_available()){ LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc"); LinphoneCoreManager *marie = linphone_core_manager_new( "marie_rc"); LinphoneCall *pauline_call, *marie_call; LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(pauline->lc); LinphoneAddress *server_addr = linphone_address_new(linphone_proxy_config_get_server_addr(proxy)); LinphoneAddress *route = linphone_address_new(linphone_proxy_config_get_route(proxy)); const char * tunnel_ip = get_ip_from_hostname("tunnel.linphone.org"); char *public_ip, *public_ip2=NULL; BC_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,1)); public_ip = get_public_contact_ip(pauline->lc); BC_ASSERT_STRING_NOT_EQUAL(public_ip, tunnel_ip); linphone_core_set_media_encryption(pauline->lc, encryption); if (with_video_and_ice){ /*we want to test that tunnel is able to work with long SIP message, above mtu. * Enable ICE and many codec to make the SIP message bigger*/ linphone_core_set_firewall_policy(marie->lc, LinphonePolicyUseIce); linphone_core_set_firewall_policy(pauline->lc, LinphonePolicyUseIce); linphone_core_enable_payload_type(pauline->lc, linphone_core_find_payload_type(pauline->lc, "speex", 32000, 1), TRUE); linphone_core_enable_payload_type(pauline->lc, linphone_core_find_payload_type(pauline->lc, "speex", 16000, 1), TRUE); linphone_core_enable_payload_type(pauline->lc, linphone_core_find_payload_type(pauline->lc, "G722", 8000, 1), TRUE); linphone_core_enable_payload_type(marie->lc, linphone_core_find_payload_type(marie->lc, "speex", 32000, 1), TRUE); linphone_core_enable_payload_type(marie->lc, linphone_core_find_payload_type(marie->lc, "speex", 16000, 1), TRUE); linphone_core_enable_payload_type(marie->lc, linphone_core_find_payload_type(marie->lc, "G722", 8000, 1), TRUE); } if (tunnel_mode != LinphoneTunnelModeDisable){ LinphoneTunnel *tunnel = linphone_core_get_tunnel(pauline->lc); LinphoneTunnelConfig *config = linphone_tunnel_config_new(); linphone_tunnel_config_set_host(config, "tunnel.linphone.org"); linphone_tunnel_config_set_port(config, 443); linphone_tunnel_config_set_remote_udp_mirror_port(config, 12345); linphone_tunnel_add_server(tunnel, config); linphone_tunnel_set_mode(tunnel, tunnel_mode); linphone_tunnel_enable_sip(tunnel, with_sip); /* * Enabling the tunnel with sip cause another REGISTER to be made. * In automatic mode, the udp test should conclude (assuming we have a normal network), that no * tunnel is needed. Thus the number of registrations should stay to 1. * The library is missing a notification of "tunnel connectivity test finished" to enable the * full testing of the automatic mode. */ if (tunnel_mode == LinphoneTunnelModeEnable && with_sip) { BC_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,2)); /* Ensure that we did use the tunnel. If so, we should see contact changed from: Contact: <sip:[email protected]>;.[...] To: Contact: <sip:[email protected]:43867>;[....] (91.121.209.194 must be tunnel.liphone.org) */ ms_free(public_ip); public_ip = get_public_contact_ip(pauline->lc); BC_ASSERT_STRING_EQUAL(public_ip, tunnel_ip); } else { public_ip2 = get_public_contact_ip(pauline->lc); BC_ASSERT_STRING_EQUAL(public_ip, public_ip2); } } BC_ASSERT_TRUE(call(pauline,marie)); pauline_call=linphone_core_get_current_call(pauline->lc); BC_ASSERT_PTR_NOT_NULL(pauline_call); if (pauline_call!=NULL){ BC_ASSERT_PTR_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(pauline_call)), encryption); } if (tunnel_mode == LinphoneTunnelModeEnable && with_sip){ /* make sure the call from pauline arrived from the tunnel by checking the contact address*/ marie_call = linphone_core_get_current_call(marie->lc); BC_ASSERT_PTR_NOT_NULL(marie_call); if (marie_call){ const char *remote_contact = linphone_call_get_remote_contact(marie_call); BC_ASSERT_PTR_NOT_NULL(remote_contact); if (remote_contact){ LinphoneAddress *tmp = linphone_address_new(remote_contact); BC_ASSERT_PTR_NOT_NULL(tmp); if (tmp){ BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(tmp), tunnel_ip); linphone_address_destroy(tmp); } } } } #ifdef VIDEO_ENABLED if (with_video_and_ice){ BC_ASSERT_TRUE(add_video(pauline, marie, TRUE)); } #endif end_call(pauline,marie); ms_free(public_ip); if(public_ip2 != NULL) ms_free(public_ip2); linphone_address_destroy(server_addr); linphone_address_destroy(route); linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie); }else{ ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__); } }
/* * could be reach : * - when the call is accepted * - when a request is accepted (pause, resume) */ static void call_accepted(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); SalMediaDescription *md; if (call==NULL){ ms_warning("No call to accept."); return ; } /*set privacy*/ call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); /* Handle remote ICE attributes if any. */ if (call->ice_session != NULL) { linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op)); } #ifdef BUILD_UPNP if (call->upnp_session != NULL) { linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op)); } #endif //BUILD_UPNP md=sal_call_get_final_media_description(op); if (md) /*make sure re-invite will not propose video again*/ call->params.has_video &= linphone_core_media_description_contains_video_stream(md); if (call->state==LinphoneCallOutgoingProgress || call->state==LinphoneCallOutgoingRinging || call->state==LinphoneCallOutgoingEarlyMedia){ linphone_call_set_state(call,LinphoneCallConnected,"Connected"); if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call); } if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){ linphone_call_update_remote_session_id_and_ver(call); if (sal_media_description_has_dir(md,SalStreamSendOnly) || sal_media_description_has_dir(md,SalStreamInactive)){ if (lc->vtable.display_status){ char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp); lc->vtable.display_status(lc,msg); ms_free(tmp); ms_free(msg); } linphone_core_update_streams (lc,call,md); linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); if (call->refer_pending) linphone_core_start_refered_call(lc,call,NULL); }else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){ /*we are put on hold when the call is initially accepted */ if (lc->vtable.display_status){ char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp); lc->vtable.display_status(lc,msg); ms_free(tmp); ms_free(msg); } linphone_core_update_streams (lc,call,md); linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote"); }else{ if (call->state!=LinphoneCallUpdating){ if (call->state==LinphoneCallResuming){ if (lc->vtable.display_status){ lc->vtable.display_status(lc,_("Call resumed.")); } }else{ if (lc->vtable.display_status){ char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call answered by %s."),tmp); lc->vtable.display_status(lc,msg); ms_free(tmp); ms_free(msg); } } } linphone_core_update_streams(lc,call,md); /*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again * further in the call, for example during pause,resume, conferencing reINVITEs*/ linphone_call_fix_call_parameters(call); if (!call->current_params.in_conference) lc->current_call=call; linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running"); } }else{ /*send a bye*/ ms_error("Incompatible SDP offer received in 200Ok, need to abort the call"); linphone_core_abort_call(lc,call,_("Incompatible, check codecs or security settings...")); } }
static int send_dtmf(MSFilter * f, uint32_t timestamp_start) { SenderData *d = (SenderData *) f->data; mblk_t *m1; int tev_type; /* create the first telephony event packet */ switch (d->dtmf){ case '1': tev_type=TEV_DTMF_1; break; case '2': tev_type=TEV_DTMF_2; break; case '3': tev_type=TEV_DTMF_3; break; case '4': tev_type=TEV_DTMF_4; break; case '5': tev_type=TEV_DTMF_5; break; case '6': tev_type=TEV_DTMF_6; break; case '7': tev_type=TEV_DTMF_7; break; case '8': tev_type=TEV_DTMF_8; break; case '9': tev_type=TEV_DTMF_9; break; case '*': tev_type=TEV_DTMF_STAR; break; case '0': tev_type=TEV_DTMF_0; break; case '#': tev_type=TEV_DTMF_POUND; break; case 'A': case 'a': tev_type=TEV_DTMF_A; break; case 'B': case 'b': tev_type=TEV_DTMF_B; break; case 'C': case 'c': tev_type=TEV_DTMF_C; break; case 'D': case 'd': tev_type=TEV_DTMF_D; break; case '!': tev_type=TEV_FLASH; break; default: ms_warning("Bad dtmf: %c.",d->dtmf); return -1; } m1=rtp_session_create_telephone_event_packet(d->session,timestamp_start==d->dtmf_ts_cur); if (m1==NULL) return -1; d->dtmf_ts_cur+=d->dtmf_ts_step; if (RTP_TIMESTAMP_IS_NEWER_THAN(d->dtmf_ts_cur, d->skip_until)) { //retransmit end of rtp dtmf event mblk_t *tmp; rtp_session_add_telephone_event(d->session,m1,tev_type,1,10,(d->dtmf_ts_cur-timestamp_start)); tmp=copymsg(m1); rtp_session_sendm_with_ts(d->session,tmp,timestamp_start); d->session->rtp.snd_seq--; tmp=copymsg(m1); rtp_session_sendm_with_ts(d->session,tmp,timestamp_start); d->session->rtp.snd_seq--; rtp_session_sendm_with_ts(d->session,m1,timestamp_start); d->skip = FALSE; d->dtmf = 0; ms_message("Finished sending RFC2833 dtmf %c",d->dtmf); }else { rtp_session_add_telephone_event(d->session,m1,tev_type,0,10,(d->dtmf_ts_cur-timestamp_start)); rtp_session_sendm_with_ts(d->session,m1,timestamp_start); } return 0; }
static void _linphone_message_storage_profile(void*data,const char*statement, sqlite3_uint64 duration){ ms_warning("SQL statement '%s' took %" PRIu64 " microseconds", statement, (uint64_t)(duration / 1000LL) ); }
static int dtmfgen_put(MSFilter *f, void *arg){ DtmfGenState *s=(DtmfGenState*)f->data; const char *dtmf=(char*)arg; s->pos=0; switch(dtmf[0]){ case '0': s->lowfreq=941; s->highfreq=1336; break; case '1': s->lowfreq=697; s->highfreq=1209; break; case '2': s->lowfreq=697; s->highfreq=1336; break; case '3': s->lowfreq=697; s->highfreq=1477; break; case '4': s->lowfreq=770; s->highfreq=1209; break; case '5': s->lowfreq=770; s->highfreq=1336; break; case '6': s->lowfreq=770; s->highfreq=1477; break; case '7': s->lowfreq=852; s->highfreq=1209; break; case '8': s->lowfreq=852; s->highfreq=1336; break; case '9': s->lowfreq=852; s->highfreq=1477; break; case '*': s->lowfreq=941; s->highfreq=1209; break; case '#': s->lowfreq=941; s->highfreq=1477; break; case 'A': s->lowfreq=697; s->highfreq=1633; break; case 'B': s->lowfreq=770; s->highfreq=1633; break; case 'C': s->lowfreq=852; s->highfreq=1633; break; case 'D': s->lowfreq=941; s->highfreq=1633; break; default: ms_warning("Not a dtmf key."); return -1; } ms_filter_lock(f); s->lowfreq=s->lowfreq/s->rate; s->highfreq=s->highfreq/s->rate; s->dur=s->rate/10; /*100 ms duration */ s->silence=0; s->dtmf=dtmf[0]; ms_filter_unlock(f); return 0; }
static void 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_response_t* response = belle_sip_response_event_get_response(event); int response_code = belle_sip_response_get_status_code(response); if (!client_transaction) { ms_warning("Discarding stateless response [%i]",response_code); return; } else { SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); belle_sip_header_contact_t* original_contact; belle_sip_header_address_t* contact_address=NULL; belle_sip_header_via_t* via_header; belle_sip_uri_t* contact_uri; unsigned int contact_port; const char* received; int rport; bool_t contact_updated=FALSE; char* new_contact; if (op->state == SalOpStateTerminated) { belle_sip_message("Op is terminated, nothing to do with this [%i]",response_code); return; } if (!op->base.remote_ua) { sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response)); } if (!op->base.call_id) { op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(response), belle_sip_header_call_id_t)))); } sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); if (op->callbacks.process_response_event) { if (op->base.root->nat_helper_enabled) { /*Fix contact if needed*/ via_header= (belle_sip_header_via_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_VIA); received = belle_sip_header_via_get_received(via_header); rport = belle_sip_header_via_get_rport(via_header); if ((original_contact=belle_sip_message_get_header_by_type(request,belle_sip_header_contact_t))) { /*update contact with sent values in any cases*/ contact_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(original_contact))); sal_op_set_contact_address(op,(const SalAddress *)contact_address); belle_sip_object_unref(contact_address); } if (sal_op_get_contact(op)){ if (received!=NULL || rport>0) { contact_address = BELLE_SIP_HEADER_ADDRESS(sal_address_clone(sal_op_get_contact_address(op))); contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_address)); if (received && strcmp(received,belle_sip_uri_get_host(contact_uri))!=0) { /*need to update host*/ belle_sip_uri_set_host(contact_uri,received); contact_updated=TRUE; } contact_port = belle_sip_uri_get_port(contact_uri); if (rport>0 && rport!=contact_port && (contact_port+rport)!=5060) { /*need to update port*/ belle_sip_uri_set_port(contact_uri,rport); contact_updated=TRUE; } /*try to fix transport if needed (very unlikely)*/ if (strcasecmp(belle_sip_header_via_get_transport(via_header),"UDP")!=0) { if (!belle_sip_uri_get_transport_param(contact_uri) ||strcasecmp(belle_sip_uri_get_transport_param(contact_uri),belle_sip_header_via_get_transport(via_header))!=0) { belle_sip_uri_set_transport_param(contact_uri,belle_sip_header_via_get_transport_lowercase(via_header)); contact_updated=TRUE; } } else { if (belle_sip_uri_get_transport_param(contact_uri)) { contact_updated=TRUE; belle_sip_uri_set_transport_param(contact_uri,NULL); } } if (contact_updated) { char* old_contact=belle_sip_object_to_string(BELLE_SIP_OBJECT(sal_op_get_contact_address(op))); new_contact=belle_sip_object_to_string(BELLE_SIP_OBJECT(contact_address)); ms_message("Updating contact from [%s] to [%s] for [%p]",old_contact,new_contact,op); sal_op_set_contact_address(op,(const SalAddress *)contact_address); belle_sip_free(new_contact); belle_sip_free(old_contact); } if (contact_address)belle_sip_object_unref(contact_address); } } } /*handle authorization*/ switch (response_code) { case 200: { break; } case 401: case 407:{ /*belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);*//*remove op from trans*/ if (op->state == SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) { /*only bye are completed*/ belle_sip_message("Op is in state terminating, nothing else to do "); } else { if (op->pending_auth_transaction){ belle_sip_object_unref(op->pending_auth_transaction); op->pending_auth_transaction=NULL; } op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); sal_process_authentication(op); return; } } } op->callbacks.process_response_event(op,event); } else { ms_error("Unhandled event response [%p]",event); } } }
static bool_t linphone_ldap_contact_provider_iterate(void *data) { LinphoneLDAPContactProvider* obj = LINPHONE_LDAP_CONTACT_PROVIDER(data); if( obj->ld && obj->connected && (obj->req_count > 0) ){ // never block struct timeval timeout = {0,0}; LDAPMessage* results = NULL; int ret = ldap_result(obj->ld, LDAP_RES_ANY, LDAP_MSG_ONE, &timeout, &results); switch( ret ){ case -1: { ms_warning("Error in ldap_result : returned -1 (req_count %d): %s", obj->req_count, ldap_err2string(errno)); break; } case 0: break; // nothing to do case LDAP_RES_BIND: { ms_error("iterate: unexpected LDAP_RES_BIND"); break; } case LDAP_RES_EXTENDED: case LDAP_RES_SEARCH_ENTRY: case LDAP_RES_SEARCH_REFERENCE: case LDAP_RES_INTERMEDIATE: case LDAP_RES_SEARCH_RESULT: { LDAPMessage* message = ldap_first_message(obj->ld, results); LinphoneLDAPContactSearch* req = linphone_ldap_contact_provider_request_search(obj, ldap_msgid(message)); while( message != NULL ){ linphone_ldap_contact_provider_handle_search_result(obj, req, message ); message = ldap_next_message(obj->ld, message); } if( req && ret == LDAP_RES_SEARCH_RESULT) linphone_ldap_contact_provider_cancel_search( LINPHONE_CONTACT_PROVIDER(obj), LINPHONE_CONTACT_SEARCH(req)); break; } case LDAP_RES_MODIFY: case LDAP_RES_ADD: case LDAP_RES_DELETE: case LDAP_RES_MODDN: case LDAP_RES_COMPARE: default: ms_message("Unhandled LDAP result %x", ret); break; } if( results ) ldap_msgfree(results); } if( obj->ld && obj->connected ){ // check for pending searches unsigned int i; for( i=0; i<obj->req_count; i++){ LinphoneLDAPContactSearch* search = (LinphoneLDAPContactSearch*)ms_list_nth_data( obj->requests, i ); if( search && search->msgid == 0){ int ret; ms_message("Found pending search %p (for %s), launching...", search, search->filter); ret = linphone_ldap_contact_provider_perform_search(obj, search); if( ret != LDAP_SUCCESS ){ linphone_ldap_contact_provider_cancel_search( LINPHONE_CONTACT_PROVIDER(obj), LINPHONE_CONTACT_SEARCH(search)); } } } } return TRUE; }
ortp_socket_t sal_get_socket(Sal *ctx){ ms_warning("sal_get_socket is deprecated"); return -1; }
static void configure_video_source(VideoStream *stream){ MSVideoSize vsize,cam_vsize; float fps=15; MSPixFmt format; bool_t encoder_has_builtin_converter = FALSE; /* transmit orientation to source filter */ ms_filter_call_method(stream->source,MS_VIDEO_CAPTURE_SET_DEVICE_ORIENTATION,&stream->device_orientation); /* transmit its preview window id if any to source filter*/ if (stream->preview_window_id!=0){ video_stream_set_native_preview_window_id(stream, stream->preview_window_id); } ms_filter_call_method(stream->ms.encoder, MS_VIDEO_ENCODER_HAS_BUILTIN_CONVERTER, &encoder_has_builtin_converter); ms_filter_call_method(stream->ms.encoder,MS_FILTER_GET_VIDEO_SIZE,&vsize); vsize=get_compatible_size(vsize,stream->sent_vsize); ms_filter_call_method(stream->source,MS_FILTER_SET_VIDEO_SIZE,&vsize); /*the camera may not support the target size and suggest a one close to the target */ ms_filter_call_method(stream->source,MS_FILTER_GET_VIDEO_SIZE,&cam_vsize); if (cam_vsize.width*cam_vsize.height<=vsize.width*vsize.height && cam_vsize.width != vsize.width){ vsize=cam_vsize; ms_message("Output video size adjusted to match camera resolution (%ix%i)\n",vsize.width,vsize.height); } else if (cam_vsize.width*cam_vsize.height>vsize.width*vsize.height){ #if TARGET_IPHONE_SIMULATOR || defined(__arm__) ms_error("Camera is proposing a size bigger than encoder's suggested size (%ix%i > %ix%i) " "Using the camera size as fallback because cropping or resizing is not implemented for arm.", cam_vsize.width,cam_vsize.height,vsize.width,vsize.height); vsize=cam_vsize; #else vsize=get_with_same_orientation(vsize,cam_vsize); ms_warning("Camera video size greater than encoder one. A scaling filter will be used!\n"); #endif } ms_filter_call_method(stream->ms.encoder,MS_FILTER_SET_VIDEO_SIZE,&vsize); ms_filter_call_method(stream->ms.encoder,MS_FILTER_GET_FPS,&fps); ms_message("Setting sent vsize=%ix%i, fps=%f",vsize.width,vsize.height,fps); /* configure the filters */ if (ms_filter_get_id(stream->source)!=MS_STATIC_IMAGE_ID) { ms_filter_call_method(stream->source,MS_FILTER_SET_FPS,&fps); } /* get the output format for webcam reader */ ms_filter_call_method(stream->source,MS_FILTER_GET_PIX_FMT,&format); if ((encoder_has_builtin_converter == TRUE) || (stream->source_performs_encoding == TRUE)) { ms_filter_call_method(stream->ms.encoder, MS_FILTER_SET_PIX_FMT, &format); } else { if (format==MS_MJPEG){ stream->pixconv=ms_filter_new(MS_MJPEG_DEC_ID); }else{ stream->pixconv = ms_filter_new(MS_PIX_CONV_ID); /*set it to the pixconv */ ms_filter_call_method(stream->pixconv,MS_FILTER_SET_PIX_FMT,&format); ms_filter_call_method(stream->pixconv,MS_FILTER_SET_VIDEO_SIZE,&cam_vsize); } stream->sizeconv=ms_filter_new(MS_SIZE_CONV_ID); ms_filter_call_method(stream->sizeconv,MS_FILTER_SET_VIDEO_SIZE,&vsize); } if (stream->ms.rc){ ms_bitrate_controller_destroy(stream->ms.rc); stream->ms.rc=NULL; } if (stream->ms.use_rc){ stream->ms.rc=ms_av_bitrate_controller_new(NULL,NULL,stream->ms.session,stream->ms.encoder); } }
void sal_reuse_authorization(Sal *ctx, bool_t enabled){ ms_warning("sal_reuse_authorization is deprecated"); return ; }
static void process_request_event(void *ud, const belle_sip_request_event_t *event) { Sal *sal=(Sal*)ud; SalOp* op=NULL; belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event); belle_sip_header_address_t* origin_address; belle_sip_header_address_t* address=NULL; belle_sip_header_from_t* from_header; belle_sip_header_to_t* to; belle_sip_response_t* resp; belle_sip_header_t *evh; const char *method=belle_sip_request_get_method(req); belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t); from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); if (dialog) { op=(SalOp*)belle_sip_dialog_get_application_data(dialog); if (op == NULL && strcmp("NOTIFY",method) == 0) { /*special case for Dialog created by notify mathing subscribe*/ belle_sip_transaction_t * sub_trans = belle_sip_dialog_get_last_transaction(dialog); op = (SalOp*)belle_sip_transaction_get_application_data(sub_trans); } if (op==NULL || op->state==SalOpStateTerminated){ ms_warning("Receiving request for null or terminated op [%p], ignored",op); return; } }else{ /*handle the case where we are receiving a request with to tag but it is not belonging to any dialog*/ belle_sip_header_to_t *to = belle_sip_message_get_header_by_type(req, belle_sip_header_to_t); if ((strcmp("INVITE",method)==0 || strcmp("NOTIFY",method)==0) && (belle_sip_header_to_get_tag(to) != NULL)) { ms_warning("Receiving %s with to-tag but no know dialog here. Rejecting.", method); resp=belle_sip_response_create_from_request(req,481); belle_sip_provider_send_response(sal->prov,resp); return; /* by default (eg. when a to-tag is present), out of dialog ACK are automatically handled in lower layers (belle-sip) but in case it misses, it will be forwarded to us */ } else if (strcmp("ACK",method)==0 && (belle_sip_header_to_get_tag(to) == NULL)) { ms_warning("Receiving ACK without to-tag but no know dialog here. Ignoring"); return; } if (strcmp("INVITE",method)==0) { op=sal_op_new(sal); op->dir=SalOpDirIncoming; sal_op_call_fill_cbs(op); }else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { op=sal_op_new(sal); op->dir=SalOpDirIncoming; if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){ sal_op_presence_fill_cbs(op); }else sal_op_subscribe_fill_cbs(op); }else if (strcmp("MESSAGE",method)==0) { op=sal_op_new(sal); op->dir=SalOpDirIncoming; sal_op_message_fill_cbs(op); }else if (strcmp("OPTIONS",method)==0) { resp=belle_sip_response_create_from_request(req,200); belle_sip_provider_send_response(sal->prov,resp); return; }else if (strcmp("INFO",method)==0) { resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/ belle_sip_provider_send_response(sal->prov,resp); return; }else if (strcmp("BYE",method)==0) { resp=belle_sip_response_create_from_request(req,481);/*out of dialog BYE */ belle_sip_provider_send_response(sal->prov,resp); return; }else if (strcmp("CANCEL",method)==0) { resp=belle_sip_response_create_from_request(req,481);/*out of dialog CANCEL */ belle_sip_provider_send_response(sal->prov,resp); return; }else if (sal->enable_test_features && strcmp("PUBLISH",method)==0) { resp=belle_sip_response_create_from_request(req,200);/*out of dialog PUBLISH */ belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_header_create("SIP-Etag","4441929FFFZQOA")); belle_sip_provider_send_response(sal->prov,resp); return; }else { ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); resp=belle_sip_response_create_from_request(req,405); belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp) ,BELLE_SIP_HEADER(belle_sip_header_allow_create("INVITE, CANCEL, ACK, BYE, SUBSCRIBE, NOTIFY, MESSAGE, OPTIONS, INFO"))); belle_sip_provider_send_response(sal->prov,resp); return; } } if (!op->base.from_address) { if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))) address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header)))) address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); else ms_error("Cannot not find from uri from request [%p]",req); sal_op_set_from_address(op,(SalAddress*)address); belle_sip_object_unref(address); } if( remote_contact ){ __sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); } if (!op->base.to_address) { to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t); if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))) address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))); else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to)))) address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to))); else ms_error("Cannot not find to uri from request [%p]",req); sal_op_set_to_address(op,(SalAddress*)address); belle_sip_object_unref(address); } if (!op->base.origin) { /*set origin uri*/ origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req)); __sal_op_set_network_origin_address(op,(SalAddress*)origin_address); belle_sip_object_unref(origin_address); } if (!op->base.remote_ua) { sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(req)); } if (!op->base.call_id) { op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_call_id_t)))); } /*It is worth noting that proxies can (and will) remove this header field*/ sal_op_set_privacy_from_message(op,(belle_sip_message_t*)req); sal_op_assign_recv_headers(op,(belle_sip_message_t*)req); if (op->callbacks && op->callbacks->process_request_event) { op->callbacks->process_request_event(op,event); } else { ms_error("sal process_request_event not implemented yet"); } }
void sal_expire_old_registration_contacts(Sal *ctx, bool_t enabled){ ms_warning("sal_expire_old_registration_contacts not implemented "); }
static void 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_response_t* response = belle_sip_response_event_get_response(event); int response_code = belle_sip_response_get_status_code(response); if (!client_transaction) { ms_warning("Discarding stateless response [%i]",response_code); return; } else { SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(response, belle_sip_header_contact_t); if (op->state == SalOpStateTerminated) { belle_sip_message("Op is terminated, nothing to do with this [%i]",response_code); return; } /*do it all the time, since we can receive provisional responses from a different instance than the final one*/ sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response)); if(remote_contact) { __sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); } if (!op->base.call_id) { op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(response), belle_sip_header_call_id_t)))); } sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); if (op->callbacks && op->callbacks->process_response_event) { /*handle authorization*/ switch (response_code) { case 200: break; case 401: case 407: if (op->state == SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) { /*only bye are completed*/ belle_sip_message("Op is in state terminating, nothing else to do "); } else { if (op->pending_auth_transaction){ belle_sip_object_unref(op->pending_auth_transaction); op->pending_auth_transaction=NULL; } if (++op->auth_requests > 2) { ms_warning("Auth info cannot be found for op [%s/%s] after 2 attempts, giving up",sal_op_get_from(op) ,sal_op_get_to(op)); op->base.root->callbacks.auth_failure(op,op->auth_info); sal_remove_pending_auth(op->base.root,op); } else { op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); sal_process_authentication(op); return; } } break; case 403: if (op->auth_info) op->base.root->callbacks.auth_failure(op,op->auth_info); break; } if (response_code >= 180 && response_code !=401 && response_code !=407 && response_code !=403) { /*not an auth request*/ op->auth_requests=0; } op->callbacks->process_response_event(op,event); } else { ms_error("Unhandled event response [%p]",event); } } }
int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, SalMediaDescription *desc ) { belle_sdp_connection_t* cnx; belle_sip_list_t* media_desc_it; belle_sdp_media_description_t* media_desc; belle_sdp_session_name_t *sname; const char* value; SalDtlsRole session_role=SalDtlsRoleInvalid; int i; desc->nb_streams = 0; desc->dir = SalStreamSendRecv; if ( ( cnx=belle_sdp_session_description_get_connection ( session_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) { strncpy ( desc->addr,belle_sdp_connection_get_address ( cnx ),sizeof ( desc->addr ) -1 ); } if ( (sname=belle_sdp_session_description_get_session_name(session_desc)) && belle_sdp_session_name_get_value(sname) ){ strncpy(desc->name,belle_sdp_session_name_get_value(sname),sizeof(desc->name) - 1); } if ( belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ) >0 ) { desc->bandwidth=belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ); } /*in some very rare case, session attribute may set stream dir*/ if ( belle_sdp_session_description_get_attribute ( session_desc,"sendrecv" ) ) { desc->dir=SalStreamSendRecv; } else if ( belle_sdp_session_description_get_attribute ( session_desc,"sendonly" ) ) { desc->dir=SalStreamSendOnly; } else if ( belle_sdp_session_description_get_attribute ( session_desc,"recvonly" ) ) { desc->dir=SalStreamRecvOnly; } else if ( belle_sdp_session_description_get_attribute ( session_desc,"inactive" ) ) { desc->dir=SalStreamInactive; } /*DTLS attributes can be defined at session level.*/ value=belle_sdp_session_description_get_attribute_value(session_desc,"setup"); if (value){ if (strncmp(value, "actpass", 7) == 0) { session_role = SalDtlsRoleUnset; } else if (strncmp(value, "active", 6) == 0) { session_role = SalDtlsRoleIsClient; } else if (strncmp(value, "passive", 7) == 0) { session_role = SalDtlsRoleIsServer; } } value=belle_sdp_session_description_get_attribute_value(session_desc,"fingerprint"); /*copy dtls attributes to every streams, might be overwritten stream by stream*/ for (i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;i++) { if (value) strncpy(desc->streams[i].dtls_fingerprint, value, sizeof(desc->streams[i].dtls_fingerprint)); desc->streams[i].dtls_role=session_role; /*set or reset value*/ } /* Get ICE remote ufrag and remote pwd, and ice_lite flag */ value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag"); if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag) - 1); value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-pwd"); if (value) strncpy(desc->ice_pwd, value, sizeof(desc->ice_pwd)-1); value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-lite"); if (value) desc->ice_lite = TRUE; /* Get session RTCP-XR attributes if any */ sdp_parse_session_rtcp_xr_parameters(session_desc, &desc->rtcp_xr); for ( media_desc_it=belle_sdp_session_description_get_media_descriptions ( session_desc ) ; media_desc_it!=NULL ; media_desc_it=media_desc_it->next ) { if (desc->nb_streams==SAL_MEDIA_DESCRIPTION_MAX_STREAMS){ ms_warning("Cannot convert mline at position [%i] from SDP to SalMediaDescription",desc->nb_streams); break; } media_desc=BELLE_SDP_MEDIA_DESCRIPTION ( media_desc_it->data ); sdp_to_stream_description(desc, media_desc); } return 0; }
static int get_local_ip_for_with_connect(int type, const char *dest, char *result){ int err,tmp; struct addrinfo hints; struct addrinfo *res=NULL; struct sockaddr_storage addr; struct sockaddr *p_addr=(struct sockaddr*)&addr; ortp_socket_t sock; socklen_t s; memset(&hints,0,sizeof(hints)); hints.ai_family=type; hints.ai_socktype=SOCK_DGRAM; /*hints.ai_flags=AI_NUMERICHOST|AI_CANONNAME;*/ err=getaddrinfo(dest,"5060",&hints,&res); if (err!=0){ ms_error("getaddrinfo() error for %s : %s",dest, gai_strerror(err)); return -1; } if (res==NULL){ ms_error("bug: getaddrinfo returned nothing."); return -1; } sock=socket(res->ai_family,SOCK_DGRAM,0); tmp=1; err=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(SOCKET_OPTION_VALUE)&tmp,sizeof(int)); if (err<0){ ms_warning("Error in setsockopt: %s",strerror(errno)); } err=connect(sock,res->ai_addr,res->ai_addrlen); if (err<0) { /*the network isn't reachable*/ if (getSocketErrorCode()!=ENETUNREACH) ms_error("Error in connect: %s",strerror(errno)); freeaddrinfo(res); close_socket(sock); return -1; } freeaddrinfo(res); res=NULL; s=sizeof(addr); err=getsockname(sock,(struct sockaddr*)&addr,&s); if (err!=0) { ms_error("Error in getsockname: %s",strerror(errno)); close_socket(sock); return -1; } if (p_addr->sa_family==AF_INET){ struct sockaddr_in *p_sin=(struct sockaddr_in*)p_addr; if (p_sin->sin_addr.s_addr==0){ close_socket(sock); return -1; } } err=getnameinfo((struct sockaddr *)&addr,s,result,LINPHONE_IPADDR_SIZE,NULL,0,NI_NUMERICHOST); if (err!=0){ ms_error("getnameinfo error: %s",strerror(errno)); } close_socket(sock); return 0; }