Exemplo n.º 1
0
/* 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;
}
Exemplo n.º 2
0
void sal_use_101(Sal *ctx, bool_t use_101){
	ms_warning("sal_use_101 is deprecated");
	return ;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
static void unimplemented_stub(){
	ms_warning("Unimplemented SAL callback");
}
Exemplo n.º 5
0
void sal_use_double_registrations(Sal *ctx, bool_t enabled){
	ms_warning("sal_use_double_registrations is deprecated");
	return ;
}
Exemplo n.º 6
0
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");
	}
}
Exemplo n.º 7
0
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");
	}

}
Exemplo n.º 8
0
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__);
}
Exemplo n.º 9
0
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__);
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
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);
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
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;
        }
    }
}
Exemplo n.º 14
0
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;
			}
		}
	}
}
Exemplo n.º 15
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);
}
Exemplo n.º 16
0
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__);
	}
}
Exemplo n.º 17
0
/*
 * 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..."));
	}
}
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
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) );
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
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);
		}
	}

}
Exemplo n.º 22
0
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;
}
Exemplo n.º 23
0
ortp_socket_t sal_get_socket(Sal *ctx){
	ms_warning("sal_get_socket is deprecated");
	return -1;
}
Exemplo n.º 24
0
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);
	}
}
Exemplo n.º 25
0
void sal_reuse_authorization(Sal *ctx, bool_t enabled){
	ms_warning("sal_reuse_authorization is deprecated");
	return ;
}
Exemplo n.º 26
0
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");
	}

}
Exemplo n.º 27
0
void sal_expire_old_registration_contacts(Sal *ctx, bool_t enabled){
	ms_warning("sal_expire_old_registration_contacts not implemented ");
}
Exemplo n.º 28
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* 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);
		}
	}
}
Exemplo n.º 29
0
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;
}
Exemplo n.º 30
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;
}