mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-03 20:46:28 +00:00
srtp: add SRTP support to Linphone
This commit is contained in:
parent
eea317e56d
commit
e700695989
11 changed files with 302 additions and 16 deletions
|
|
@ -491,6 +491,20 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
|
|||
lc->vtable.display_status(lc,msg600);
|
||||
break;
|
||||
case SalReasonMedia:
|
||||
//media_encryption_mandatory
|
||||
if (call->params.media_encryption == LinphoneMediaEncryptionSRTP &&
|
||||
!linphone_core_is_media_encryption_mandatory(lc)) {
|
||||
int i;
|
||||
ms_message("Outgoing call failed with SRTP (SAVP) enabled - retrying with AVP");
|
||||
/* clear SRTP local params */
|
||||
call->params.media_encryption = LinphoneMediaEncryptionNone;
|
||||
for(i=0; i<call->localdesc->nstreams; i++) {
|
||||
call->localdesc->streams[i].proto = SalProtoRtpAvp;
|
||||
memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
|
||||
}
|
||||
linphone_core_start_invite(lc, call, NULL);
|
||||
return;
|
||||
}
|
||||
msg=_("No common codecs");
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "lpconfig.h"
|
||||
#include "private.h"
|
||||
#include <ortp/event.h>
|
||||
#include <ortp/b64.h>
|
||||
|
||||
|
||||
#include "mediastreamer2/mediastream.h"
|
||||
|
|
@ -41,6 +42,27 @@ static MSWebCam *get_nowebcam_device(){
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool_t generate_b64_crypto_key(int key_length, char* key_out) {
|
||||
int b64_size;
|
||||
uint8_t* tmp = (uint8_t*) malloc(key_length);
|
||||
if (crypto_get_random(tmp, key_length)) {
|
||||
ms_error("Failed to generate random key");
|
||||
free(tmp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
b64_size = b64_encode((const char*)tmp, key_length, NULL, 0);
|
||||
if (b64_size == 0) {
|
||||
ms_error("Failed to b64 encode key");
|
||||
free(tmp);
|
||||
return FALSE;
|
||||
}
|
||||
key_out[b64_size] = '\0';
|
||||
b64_encode((const char*)tmp, key_length, key_out, 40);
|
||||
free(tmp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LinphoneCore *linphone_call_get_core(const LinphoneCall *call){
|
||||
return call->core;
|
||||
}
|
||||
|
|
@ -165,6 +187,7 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
|
|||
static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, LinphoneCall *call, unsigned int session_id, unsigned int session_ver){
|
||||
MSList *l;
|
||||
PayloadType *pt;
|
||||
int i;
|
||||
const char *me=linphone_core_get_identity(lc);
|
||||
LinphoneAddress *addr=linphone_address_new(me);
|
||||
const char *username=linphone_address_get_username (addr);
|
||||
|
|
@ -180,7 +203,8 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
|
|||
/*set audio capabilities */
|
||||
strncpy(md->streams[0].addr,call->localip,sizeof(md->streams[0].addr));
|
||||
md->streams[0].port=call->audio_port;
|
||||
md->streams[0].proto=SalProtoRtpAvp;
|
||||
md->streams[0].proto=(call->params.media_encryption == LinphoneMediaEncryptionSRTP) ?
|
||||
SalProtoRtpSavp : SalProtoRtpAvp;
|
||||
md->streams[0].type=SalAudio;
|
||||
md->streams[0].ptime=lc->net_conf.down_ptime;
|
||||
l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw);
|
||||
|
|
@ -192,11 +216,26 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
|
|||
if (call->params.has_video){
|
||||
md->nstreams++;
|
||||
md->streams[1].port=call->video_port;
|
||||
md->streams[1].proto=SalProtoRtpAvp;
|
||||
md->streams[1].proto=md->streams[0].proto;
|
||||
md->streams[1].type=SalVideo;
|
||||
l=make_codec_list(lc,lc->codecs_conf.video_codecs,0);
|
||||
md->streams[1].payloads=l;
|
||||
}
|
||||
|
||||
for(i=0; i<md->nstreams; i++) {
|
||||
if (md->streams[i].proto == SalProtoRtpSavp) {
|
||||
md->streams[i].crypto[0].tag = 1;
|
||||
md->streams[i].crypto[0].algo = AES_128_SHA1_80;
|
||||
if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key))
|
||||
md->streams[i].crypto[0].algo = 0;
|
||||
md->streams[i].crypto[1].tag = 2;
|
||||
md->streams[i].crypto[1].algo = AES_128_SHA1_32;
|
||||
if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key))
|
||||
md->streams[i].crypto[1].algo = 0;
|
||||
md->streams[i].crypto[2].algo = 0;
|
||||
}
|
||||
}
|
||||
|
||||
linphone_address_destroy(addr);
|
||||
return md;
|
||||
}
|
||||
|
|
@ -315,6 +354,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
|
||||
linphone_call_init_common(call, from, to);
|
||||
call->params.has_video=linphone_core_video_enabled(lc);
|
||||
call->params.media_encryption=linphone_core_get_media_encryption(lc);
|
||||
call->localdesc=create_local_media_description (lc,call);
|
||||
call->camera_active=call->params.has_video;
|
||||
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun)
|
||||
|
|
@ -973,7 +1013,12 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
LinphoneCore *lc=call->core;
|
||||
int jitt_comp=lc->rtp_conf.audio_jitt_comp;
|
||||
int used_pt=-1;
|
||||
/* look for savp stream first */
|
||||
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpSavp,SalAudio);
|
||||
/* no savp audio stream, use avp */
|
||||
if (!stream)
|
||||
stream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpAvp,SalAudio);
|
||||
|
||||
if (stream && stream->dir!=SalStreamInactive && stream->port!=0){
|
||||
|
|
@ -1050,6 +1095,17 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
/*transform the graph to connect it to the conference filter */
|
||||
linphone_call_add_to_conf(call);
|
||||
}
|
||||
|
||||
if (stream->proto == SalProtoRtpSavp) {
|
||||
const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,
|
||||
SalProtoRtpSavp,SalAudio);
|
||||
|
||||
audio_stream_enable_strp(
|
||||
call->audiostream,
|
||||
stream->crypto[0].algo,
|
||||
local_st_desc->crypto[0].master_key,
|
||||
stream->crypto[0].master_key);
|
||||
}
|
||||
}else ms_warning("No audio stream accepted ?");
|
||||
}
|
||||
}
|
||||
|
|
@ -1058,8 +1114,14 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
#ifdef VIDEO_ENABLED
|
||||
LinphoneCore *lc=call->core;
|
||||
int used_pt=-1;
|
||||
/* look for savp stream first */
|
||||
const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpAvp,SalVideo);
|
||||
SalProtoRtpSavp,SalVideo);
|
||||
/* no savp audio stream, use avp */
|
||||
if (!vstream)
|
||||
vstream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpAvp,SalVideo);
|
||||
|
||||
/* shutdown preview */
|
||||
if (lc->previewstream!=NULL) {
|
||||
video_preview_stop(lc->previewstream);
|
||||
|
|
@ -1114,6 +1176,18 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
used_pt, lc->rtp_conf.audio_jitt_comp, cam);
|
||||
video_stream_set_rtcp_information(call->videostream, cname,LINPHONE_RTCP_SDES_TOOL);
|
||||
}
|
||||
|
||||
if (vstream->proto == SalProtoRtpSavp) {
|
||||
const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,
|
||||
SalProtoRtpSavp,SalVideo);
|
||||
|
||||
video_stream_enable_strp(
|
||||
call->videostream,
|
||||
vstream->crypto[0].algo,
|
||||
local_st_desc->crypto[0].master_key,
|
||||
vstream->crypto[0].master_key
|
||||
);
|
||||
}
|
||||
}else ms_warning("No video stream accepted.");
|
||||
}else{
|
||||
ms_warning("No valid video stream defined.");
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/*#define UNSTANDART_GSM_11K 1*/
|
||||
|
||||
static const char *liblinphone_version=LIBLINPHONE_VERSION;
|
||||
|
|
@ -515,7 +519,7 @@ static void sip_config_read(LinphoneCore *lc)
|
|||
}
|
||||
|
||||
sal_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", "/etc/ssl/certs"));
|
||||
|
||||
|
||||
tmp=lp_config_get_int(lc->config,"sip","guess_hostname",1);
|
||||
linphone_core_set_guess_hostname(lc,tmp);
|
||||
|
||||
|
|
@ -4231,7 +4235,9 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc){
|
|||
|
||||
LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc){
|
||||
LinphoneCallParams *p=ms_new0(LinphoneCallParams,1);
|
||||
p->has_video=linphone_core_video_enabled(lc);
|
||||
p->has_video=linphone_core_video_enabled(lc);
|
||||
p->media_encryption=linphone_core_get_media_encryption(lc);
|
||||
ms_message("%s : %d", __FUNCTION__, p->media_encryption);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
@ -4347,3 +4353,37 @@ const LinphoneCall* linphone_core_find_call_from_uri(LinphoneCore *lc, const cha
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void linphone_core_set_srtp_enabled(LinphoneCore *lc, bool_t enabled) {
|
||||
lp_config_set_int(lc->config,"sip","srtp",(int)enabled);
|
||||
}
|
||||
|
||||
void linphone_core_set_media_encryption_enabled(LinphoneCore *lc, enum LinphoneMediaEncryption menc) {
|
||||
if (menc == LinphoneMediaEncryptionSRTP)
|
||||
lp_config_set_string(lc->config,"sip","media_encryption","srtp");
|
||||
else if (menc == LinphoneMediaEncryptionZRTP)
|
||||
lp_config_set_string(lc->config,"sip","media_encryption","zrtp");
|
||||
else
|
||||
lp_config_set_string(lc->config,"sip","media_encryption","none");
|
||||
}
|
||||
|
||||
enum LinphoneMediaEncryption linphone_core_get_media_encryption(LinphoneCore *lc) {
|
||||
const char* menc = lp_config_get_string(lc->config, "sip", "media_encryption", NULL);
|
||||
|
||||
if (menc == NULL)
|
||||
return LinphoneMediaEncryptionNone;
|
||||
else if (strcmp(menc, "srtp")==0)
|
||||
return LinphoneMediaEncryptionSRTP;
|
||||
else if (strcmp(menc, "zrtp")==0)
|
||||
return LinphoneMediaEncryptionZRTP;
|
||||
else
|
||||
return LinphoneMediaEncryptionNone;
|
||||
}
|
||||
|
||||
bool_t linphone_core_is_media_encryption_mandatory(LinphoneCore *lc) {
|
||||
return (bool_t)lp_config_get_int(lc->config, "sip", "media_encryption_mandatory", 0);
|
||||
}
|
||||
|
||||
void linphone_core_set_media_encryption_mandatory(LinphoneCore *lc, bool_t m) {
|
||||
lp_config_set_int(lc->config, "sip", "media_encryption_mandatory", (int)m);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,11 @@ typedef struct _LinphoneCallLog{
|
|||
struct _LinphoneCore *lc;
|
||||
} LinphoneCallLog;
|
||||
|
||||
|
||||
enum LinphoneMediaEncryption {
|
||||
LinphoneMediaEncryptionNone,
|
||||
LinphoneMediaEncryptionSRTP,
|
||||
LinphoneMediaEncryptionZRTP
|
||||
};
|
||||
|
||||
/*public: */
|
||||
void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up);
|
||||
|
|
@ -1029,6 +1033,12 @@ int linphone_core_leave_conference(LinphoneCore *lc);
|
|||
int linphone_core_terminate_conference(LinphoneCore *lc);
|
||||
int linphone_core_get_conference_size(LinphoneCore *lc);
|
||||
|
||||
void linphone_core_set_media_encryption_enabled(LinphoneCore *lc, enum LinphoneMediaEncryption menc);
|
||||
enum LinphoneMediaEncryption linphone_core_get_media_encryption(LinphoneCore *lc);
|
||||
|
||||
bool_t linphone_core_is_media_encryption_mandatory(LinphoneCore *lc);
|
||||
void linphone_core_set_media_encryption_mandatory(LinphoneCore *lc, bool_t m);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -128,6 +128,31 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
|
|||
return res;
|
||||
}
|
||||
|
||||
static bool_t match_crypto_algo(const SalSrtpCryptoAlgo* local, const SalSrtpCryptoAlgo* remote,
|
||||
SalSrtpCryptoAlgo* result, bool_t use_local_key) {
|
||||
int i,j;
|
||||
for(i=0; i<SAL_CRYPTO_ALGO_MAX; i++) {
|
||||
if (remote[i].algo == 0)
|
||||
break;
|
||||
|
||||
for(j=0; j<SAL_CRYPTO_ALGO_MAX; j++) {
|
||||
if (remote[i].algo == local[j].algo) {
|
||||
result->algo = remote[i].algo;
|
||||
if (use_local_key) {
|
||||
strncpy(result->master_key, local[j].master_key, 41);
|
||||
result->tag = local[j].tag;
|
||||
} else {
|
||||
strncpy(result->master_key, remote[j].master_key, 41);
|
||||
result->tag = remote[j].tag;
|
||||
}
|
||||
result->master_key[40] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static SalStreamDir compute_dir_outgoing(SalStreamDir local, SalStreamDir answered){
|
||||
|
|
@ -174,7 +199,7 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
|
|||
SalStreamDescription *result){
|
||||
if (remote_answer->port!=0)
|
||||
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE);
|
||||
result->proto=local_offer->proto;
|
||||
result->proto=remote_answer->proto;
|
||||
result->type=local_offer->type;
|
||||
result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
|
||||
|
||||
|
|
@ -186,6 +211,12 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
|
|||
}else{
|
||||
result->port=0;
|
||||
}
|
||||
if (result->proto == SalProtoRtpSavp) {
|
||||
/* verify crypto algo */
|
||||
memset(result->crypto, 0, sizeof(result->crypto));
|
||||
if (!match_crypto_algo(local_offer->crypto, remote_answer->crypto, &result->crypto[0], FALSE))
|
||||
result->port = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -193,7 +224,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
|
|||
const SalStreamDescription *remote_offer,
|
||||
SalStreamDescription *result, bool_t one_matching_codec){
|
||||
result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec);
|
||||
result->proto=local_cap->proto;
|
||||
result->proto=remote_offer->proto;
|
||||
result->type=local_cap->type;
|
||||
result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir);
|
||||
if (result->payloads && !only_telephone_event(result->payloads)){
|
||||
|
|
@ -205,6 +236,13 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
|
|||
}else{
|
||||
result->port=0;
|
||||
}
|
||||
if (result->proto == SalProtoRtpSavp) {
|
||||
/* select crypto algo */
|
||||
memset(result->crypto, 0, sizeof(result->crypto));
|
||||
if (!match_crypto_algo(local_cap->crypto, remote_offer->crypto, &result->crypto[0], TRUE))
|
||||
result->port = 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -215,6 +253,7 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
|
|||
const SalMediaDescription *remote_answer,
|
||||
SalMediaDescription *result){
|
||||
int i,j;
|
||||
|
||||
const SalStreamDescription *ls,*rs;
|
||||
for(i=0,j=0;i<local_offer->nstreams;++i){
|
||||
ms_message("Processing for stream %i",i);
|
||||
|
|
@ -246,10 +285,18 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
|
|||
for(i=0;i<remote_offer->nstreams;++i){
|
||||
rs=&remote_offer->streams[i];
|
||||
ms_message("Processing for stream %i",i);
|
||||
|
||||
ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,rs->proto,rs->type);
|
||||
ms_message("remote proto: %s => %p", (rs->proto == SalProtoRtpAvp)?"AVP":"SAVP", ls);
|
||||
/* if matching failed, and remote proposes Avp only, ask for local Savp streams */
|
||||
if (!ls && rs->proto == SalProtoRtpAvp) {
|
||||
ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,SalProtoRtpSavp,rs->type);
|
||||
ms_message("retry with AVP => %p", ls);
|
||||
}
|
||||
if (ls){
|
||||
initiate_incoming(ls,rs,&result->streams[i],one_matching_codec);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
/* create an inactive stream for the answer, as there where no matching stream a local capability */
|
||||
result->streams[i].dir=SalStreamInactive;
|
||||
result->streams[i].port=0;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
struct _LinphoneCallParams{
|
||||
LinphoneCall *referer; /*in case this call creation is consecutive to an incoming transfer, this points to the original call */
|
||||
int audio_bw; /* bandwidth limit for audio stream */
|
||||
|
|
@ -65,6 +64,7 @@ struct _LinphoneCallParams{
|
|||
bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/
|
||||
bool_t in_conference; /*in conference mode */
|
||||
bool_t pad;
|
||||
enum LinphoneMediaEncryption media_encryption;
|
||||
};
|
||||
|
||||
struct _LinphoneCall
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define sal_h
|
||||
|
||||
#include "mediastreamer2/mscommon.h"
|
||||
#include "ortp/srtp.h"
|
||||
|
||||
/*Dirty hack, keep in sync with mediastreamer2/include/mediastream.h */
|
||||
#ifndef PAYLOAD_TYPE_FLAG_CAN_RECV
|
||||
|
|
@ -111,6 +112,15 @@ typedef struct SalEndpointCandidate{
|
|||
|
||||
#define SAL_ENDPOINT_CANDIDATE_MAX 2
|
||||
|
||||
typedef struct SalSrtpCryptoAlgo {
|
||||
unsigned int tag;
|
||||
enum ortp_srtp_crypto_suite_t algo;
|
||||
/* 41= 40 max(key_length for all algo) + '\0' */
|
||||
char master_key[41];
|
||||
} SalSrtpCryptoAlgo;
|
||||
|
||||
#define SAL_CRYPTO_ALGO_MAX 4
|
||||
|
||||
typedef struct SalStreamDescription{
|
||||
SalMediaProto proto;
|
||||
SalStreamType type;
|
||||
|
|
@ -122,6 +132,7 @@ typedef struct SalStreamDescription{
|
|||
int ptime;
|
||||
SalEndpointCandidate candidates[SAL_ENDPOINT_CANDIDATE_MAX];
|
||||
SalStreamDir dir;
|
||||
SalSrtpCryptoAlgo crypto[SAL_CRYPTO_ALGO_MAX];
|
||||
} SalStreamDescription;
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
|
||||
|
|
|
|||
|
|
@ -514,12 +514,18 @@ static void sdp_process(SalOp *h){
|
|||
It should contains media parameters constraint from the remote offer, not our response*/
|
||||
strcpy(h->result->addr,h->base.remote_media->addr);
|
||||
h->result->bandwidth=h->base.remote_media->bandwidth;
|
||||
|
||||
//remplacer la cle
|
||||
for(i=0;i<h->result->nstreams;++i){
|
||||
if (h->result->streams[i].port>0){
|
||||
strcpy(h->result->streams[i].addr,h->base.remote_media->streams[i].addr);
|
||||
h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
|
||||
h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
|
||||
h->result->streams[i].port=h->base.remote_media->streams[i].port;
|
||||
|
||||
if (h->result->streams[i].proto == SalProtoRtpSavp) {
|
||||
h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -545,6 +551,8 @@ int sal_call(SalOp *h, const char *from, const char *to){
|
|||
sal_op_set_from(h,from);
|
||||
sal_op_set_to(h,to);
|
||||
sal_exosip_fix_route(h);
|
||||
|
||||
h->terminated = FALSE;
|
||||
err=eXosip_call_build_initial_invite(&invite,to,from,sal_op_get_route(h),"Phone call");
|
||||
if (err!=0){
|
||||
ms_error("Could not create call.");
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
|
||||
#include "ortp/b64.h"
|
||||
#include "ortp/srtp.h"
|
||||
#include "sal.h"
|
||||
#include <eXosip2/eXosip.h>
|
||||
|
||||
|
|
@ -233,9 +234,47 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
|
|||
osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (addr), NULL, NULL);
|
||||
}
|
||||
sdp_message_m_media_add (msg, osip_strdup (mt),
|
||||
int_2char (port), NULL,
|
||||
osip_strdup ("RTP/AVP"));
|
||||
|
||||
if (desc->proto == SalProtoRtpSavp) {
|
||||
int i;
|
||||
|
||||
sdp_message_m_media_add (msg, osip_strdup (mt),
|
||||
int_2char (port), NULL,
|
||||
osip_strdup ("RTP/SAVP"));
|
||||
|
||||
/* add crypto lines */
|
||||
for(i=0; i<SAL_CRYPTO_ALGO_MAX; i++) {
|
||||
char buffer[1024];
|
||||
switch (desc->crypto[i].algo) {
|
||||
case AES_128_SHA1_80:
|
||||
snprintf(buffer, 1024, "%d %s inline:%s",
|
||||
desc->crypto[i].tag, "AES_CM_128_HMAC_SHA1_80", desc->crypto[i].master_key);
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("crypto"),
|
||||
osip_strdup(buffer));
|
||||
break;
|
||||
case AES_128_SHA1_32:
|
||||
snprintf(buffer, 1024, "%d %s inline:%s",
|
||||
desc->crypto[i].tag, "AES_CM_128_HMAC_SHA1_32", desc->crypto[i].master_key);
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("crypto"),
|
||||
osip_strdup(buffer));
|
||||
break;
|
||||
case AES_128_NO_AUTH:
|
||||
ms_warning("Unsupported crypto suite: AES_128_NO_AUTH");
|
||||
break;
|
||||
case NO_CIPHER_SHA1_80:
|
||||
ms_warning("Unsupported crypto suite: NO_CIPHER_SHA1_80");
|
||||
break;
|
||||
default:
|
||||
i = SAL_CRYPTO_ALGO_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
sdp_message_m_media_add (msg, osip_strdup (mt),
|
||||
int_2char (port), NULL,
|
||||
osip_strdup ("RTP/AVP"));
|
||||
|
||||
}
|
||||
if (desc->bandwidth>0) sdp_message_b_bandwidth_add (msg, lineno, osip_strdup ("AS"),
|
||||
int_2char(desc->bandwidth));
|
||||
if (desc->ptime>0) sdp_message_a_attribute_add(msg,lineno,osip_strdup("ptime"),
|
||||
|
|
@ -355,7 +394,7 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
|||
for(j=0;(sbw=sdp_message_bandwidth_get(msg,i,j))!=NULL;++j){
|
||||
if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth);
|
||||
}
|
||||
stream->dir=_sdp_message_get_mline_dir(msg,i);
|
||||
stream->dir=_sdp_message_get_mline_dir(msg,i);
|
||||
/* for each payload type */
|
||||
for (j=0;((number=sdp_message_m_payload_get (msg, i,j)) != NULL); j++){
|
||||
const char *rtpmap,*fmtp;
|
||||
|
|
@ -373,6 +412,49 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
|||
pt->send_fmtp ? pt->send_fmtp : "");
|
||||
}
|
||||
}
|
||||
|
||||
/* read crypto lines if any */
|
||||
if (stream->proto == SalProtoRtpSavp) {
|
||||
int k, valid_count = 0;
|
||||
sdp_attribute_t *attr;
|
||||
|
||||
memset(&stream->crypto, 0, sizeof(stream->crypto));
|
||||
for (k=0;valid_count < SAL_CRYPTO_ALGO_MAX && (attr=sdp_message_attribute_get(msg,i,k))!=NULL;k++){
|
||||
char tmp[256], tmp2[256];
|
||||
if (keywordcmp("crypto",attr->a_att_field)==0 && attr->a_att_value!=NULL){
|
||||
int nb = sscanf(attr->a_att_value, "%d %256s inline:%256s",
|
||||
&stream->crypto[valid_count].tag,
|
||||
tmp,
|
||||
tmp2);
|
||||
ms_message("Found valid crypto line (tag:%d algo:'%s' key:'%s'",
|
||||
stream->crypto[valid_count].tag,
|
||||
tmp,
|
||||
tmp2);
|
||||
if (nb == 3) {
|
||||
if (strcmp(tmp, "AES_CM_128_HMAC_SHA1_80") == 0)
|
||||
stream->crypto[valid_count].algo = AES_128_SHA1_80;
|
||||
else if (strcmp(tmp, "AES_CM_128_HMAC_SHA1_32") == 0)
|
||||
stream->crypto[valid_count].algo = AES_128_SHA1_32;
|
||||
else {
|
||||
ms_warning("Failed to parse crypto-algo: '%s'", tmp);
|
||||
stream->crypto[valid_count].algo = 0;
|
||||
}
|
||||
if (stream->crypto[valid_count].algo) {
|
||||
strncpy(stream->crypto[valid_count].master_key, tmp2, 41);
|
||||
stream->crypto[valid_count].master_key[40] = '\0';
|
||||
ms_message("Found valid crypto line (tag:%d algo:'%s' key:'%s'",
|
||||
stream->crypto[valid_count].tag,
|
||||
tmp,
|
||||
stream->crypto[valid_count].master_key);
|
||||
valid_count++;
|
||||
}
|
||||
} else {
|
||||
ms_warning("sdp has a strange a= line (%s) nb=%i",attr->a_att_value,nb);
|
||||
}
|
||||
}
|
||||
}
|
||||
ms_message("Found: %d valid crypto lines", valid_count);
|
||||
}
|
||||
}
|
||||
desc->nstreams=i;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 28a643d20f6d6384d96590ab6e988928597878cf
|
||||
Subproject commit aadeaaa8b2de3b1e0cb9ffd5a0a22a85335e7951
|
||||
2
oRTP
2
oRTP
|
|
@ -1 +1 @@
|
|||
Subproject commit 845e0cf4e33cc9964c48aa9191005d4108dfebbd
|
||||
Subproject commit 3e3ba3f4922a9f2eaddd782b571abf3968aa41b9
|
||||
Loading…
Add table
Reference in a new issue