Merge remote-tracking branch 'linphone/master' into daemon

This commit is contained in:
Simon Morlat 2015-03-19 11:40:08 +01:00
commit c6b2bd9032
12 changed files with 413 additions and 233 deletions

View file

@ -1,6 +1,7 @@
LOCAL_PATH := $(call my-dir)/../../tester
common_SRC_FILES := \
../../belle-sip/tester/common/bc_tester_utils.c \
call_tester.c \
liblinphone_tester.c \
message_tester.c \
@ -21,14 +22,15 @@ common_SRC_FILES := \
accountmanager.c \
offeranswer_tester.c \
multicast_call_tester.c \
multi_call.c
multi_call.c \
common_C_INCLUDES += \
$(LOCAL_PATH) \
$(LOCAL_PATH)/../include \
$(LOCAL_PATH)/../coreapi \
$(LOCAL_PATH)/../oRTP/include \
$(LOCAL_PATH)/../mediastreamer2/include
$(LOCAL_PATH)/../mediastreamer2/include \
$(LOCAL_PATH)/../../belle-sip/tester/common \
include $(CLEAR_VARS)
@ -37,7 +39,7 @@ LOCAL_MODULE := liblinphone_tester
LOCAL_MODULE_FILENAME := liblinphone_tester-$(TARGET_ARCH_ABI)
LOCAL_SRC_FILES += $(common_SRC_FILES)
LOCAL_C_INCLUDES = $(common_C_INCLUDES)
LOCAL_CFLAGS = -DIN_LINPHONE
LOCAL_CFLAGS = -DIN_LINPHONE -DBC_CONFIG_FILE=\"config.h\"
LOCAL_LDLIBS := -llog -lz
ifeq ($(BUILD_MATROSKA), 1)

View file

@ -609,6 +609,7 @@ AC_ARG_ENABLE(alsa,
[alsa=true]
)
dnl this options are just for passing to mediastreamer2 subproject
AC_ARG_ENABLE(zrtp,
[AS_HELP_STRING([--enable-zrtp], [Turn on zrtp support])],
[case "${enableval}" in
@ -619,6 +620,7 @@ AC_ARG_ENABLE(zrtp,
[zrtp=false]
)
dnl this options are just for passing to mediastreamer2 subproject
AC_ARG_ENABLE(dtls,
[AS_HELP_STRING([--enable-dtls], [Turn on dtls support - requires polarssl > 1.4])],
[case "${enableval}" in
@ -639,6 +641,60 @@ AC_ARG_ENABLE(g729bCN,
[g729bCN=false]
)
dnl Polarssl lib is requested for Lime
AC_ARG_WITH( polarssl,
[ --with-polarssl Set prefix where polarssl can be found (ex:/usr, /usr/local)[[default=PREFIX or /usr if NONE]] ],
[ polarssl_prefix=${withval}],[ if test "$prefix" != "NONE"; then
polarssl_prefix=${prefix}
else
polarssl_prefix="/usr"
fi ])
found_polarssl=no
if test "$polarssl_prefix" != "none" ; then
if test "$polarssl_prefix" != "/usr" ; then
POLARSSL_CFLAGS="-I${polarssl_prefix}/include"
POLARSSL_LIBS="-L${polarssl_prefix}/lib"
fi
POLARSSL_LIBS="$POLARSSL_LIBS -lpolarssl"
CPPFLAGS_save=$CPPFLAGS
LIBS_save=$LIBS
CPPFLAGS="$CPPFLAGS $POLARSSL_CFLAGS"
LIBS="$LIBS $POLARSSL_LIBS"
AC_CHECK_HEADERS(polarssl/gcm.h,
[found_polarssl=yes; AC_MSG_NOTICE([polarssl usable])],
[POLARSSL_CFLAGS=""
POLARSSL_LIBS=""])
CPPFLAGS=$CPPFLAGS_save
LIBS=$LIBS_save
fi
dnl check for Lime support, need polarssl version >= 1.3 (with gcm.h)
AC_ARG_ENABLE(lime,
[AS_HELP_STRING([--enable-lime], [Turn on or off compilation of Instant Messaging Encryption (default=auto)])],
[case "${enableval}" in
yes) lime=true ;;
no) lime=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-lime) ;;
esac],
[lime=auto]
)
if test "$lime" != "false" ; then
if test "x$found_polarssl" != "xyes" ; then
if test "$lime" = "true" ; then
AC_MSG_ERROR("LIME requires POLARSSL in version >= 1.3")
fi
lime=false
else
AC_DEFINE(HAVE_LIME, 1, [Defined when LIME support is compiled])
lime=true
fi
fi
dnl build console if required
AM_CONDITIONAL(BUILD_CONSOLE, test x$console_ui = xtrue)
@ -648,8 +704,6 @@ AM_CONDITIONAL(ARMBUILD, test x$use_arm_toolchain = xyes)
dnl compilation of gtk user interface
AM_CONDITIONAL(BUILD_GTK_UI, [test x$gtk_ui = xtrue ] )
AM_CONDITIONAL(BUILD_WIN32, test x$mingw_found = xyes )
AM_CONDITIONAL(BUILD_ZRTP, test x$zrtp = xtrue)
AM_CONDITIONAL(BUILD_DTLS, test x$dtls = xtrue)
dnl check getenv
AH_TEMPLATE([HAVE_GETENV])
@ -1000,8 +1054,7 @@ printf "* %-30s %s\n" "Account assistant" $build_wizard
printf "* %-30s %s\n" "Console interface" $console_ui
printf "* %-30s %s\n" "Tools" $build_tools
printf "* %-30s %s\n" "Message storage" $enable_msg_storage
printf "* %-30s %s\n" "zRTP encryption" $zrtp
printf "* %-30s %s\n" "DTLS encryption" $dtls
printf "* %-30s %s\n" "IM encryption" $lime
printf "* %-30s %s\n" "uPnP support" $build_upnp
printf "* %-30s %s\n" "LDAP support" $enable_ldap
printf "* %-30s %s\n" "ZLIB support" $found_zlib

View file

@ -1,4 +1,10 @@
#include "lime.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_LIME
#include "linphonecore.h"
#include "ortp/b64.h"
#include "polarssl/gcm.h"
@ -11,6 +17,14 @@
#else /* for Polarssl version 1.2 */
#include "polarssl/sha2.h"
#endif
/**
* @brief check at runtime if LIME is available
*
* @return TRUE when Lime was fully compiled, FALSE when it wasn't
*/
bool_t lime_is_available() { return TRUE; }
/**
* @brief convert an hexa char [0-9a-fA-F] into the corresponding unsigned integer value
* Any invalid char will be converted to zero without any warning
@ -89,7 +103,15 @@ void lime_int8ToStr(uint8_t *outputString, uint8_t *inputBytes, uint16_t inputBy
int lime_getSelfZid(xmlDocPtr cacheBuffer, uint8_t selfZid[25]) {
/**
* @brief Retrieve selfZID from cache
*
* @param[in] cacheBuffer The xmlDoc containing current cache
* @param[out] selfZid The ZID found as a 24 hexa char string null terminated
*
* @return 0 on success, error code otherwise
*/
static int lime_getSelfZid(xmlDocPtr cacheBuffer, uint8_t selfZid[25]) {
xmlNodePtr cur;
xmlChar *selfZidHex;
@ -379,7 +401,15 @@ int lime_setCachedKey(xmlDocPtr cacheBuffer, limeKey_t *associatedKey, uint8_t r
return 0;
}
int lime_deriveKey(limeKey_t *key) {
/**
* @brief Derive in place the key given in parameter and increment session index
* Derivation is made derived Key = HMAC_SHA256(Key, 0x0000001||"MessageKey"||0x00||SessionId||SessionIndex||256)
*
* @param[in/out] key The structure containing the original key which will be overwritten, the sessionId and SessionIndex
*
* @return 0 on success, error code otherwise
*/
static int lime_deriveKey(limeKey_t *key) {
uint8_t inputData[55];
uint8_t derivedKey[32];
@ -779,6 +809,18 @@ int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_
return 0;
}
#else /* HAVE_LIME */
bool_t lime_is_available() { return FALSE; }
int lime_decryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) { return LIME_NOT_ENABLED;}
int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_t **output) { return LIME_NOT_ENABLED;}
int lime_createMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_t *peerURI, uint8_t **output) { return LIME_NOT_ENABLED;}
int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) {return LIME_NOT_ENABLED;}
#endif /* HAVE_LIME */
char *lime_error_code_to_string(int errorCode) {
switch (errorCode) {
case LIME_INVALID_CACHE: return "Invalid ZRTP cache";
@ -787,6 +829,7 @@ char *lime_error_code_to_string(int errorCode) {
case LIME_UNABLE_TO_DECRYPT_MESSAGE: return "Unable to decrypt message";
case LIME_NO_VALID_KEY_FOUND_FOR_PEER: return "No valid key found";
case LIME_INVALID_ENCRYPTED_MESSAGE: return "Invalid encrypted message";
case LIME_NOT_ENABLED: return "Lime not enabled at build";
}
return "Unknow error";

View file

@ -7,6 +7,7 @@
#define LIME_UNABLE_TO_DECRYPT_MESSAGE 0x1008
#define LIME_NO_VALID_KEY_FOUND_FOR_PEER 0x1010
#define LIME_INVALID_ENCRYPTED_MESSAGE 0x1020
#define LIME_NOT_ENABLED 0x1100
/* this define the maximum key derivation number allowed to get the caches back in sync in case of missed messages */
#define MAX_DERIVATION_NUMBER 100
@ -41,16 +42,6 @@ typedef struct limeURIKeys_struct {
uint8_t *peerURI; /**< the sip URI associated to all the keys, must be a null terminated string */
} limeURIKeys_t;
/**
* @brief Retrieve selfZID from cache
*
* @param[in] cacheBuffer The xmlDoc containing current cache
* @param[out] selfZid The ZID found as a 24 hexa char string null terminated
*
* @return 0 on success, error code otherwise
*/
LINPHONE_PUBLIC int lime_getSelfZid(xmlDocPtr cacheBuffer, uint8_t selfZid[25]);
/**
* @brief Get from cache all the senders keys associated to the given URI
* peerKeys field from associatedKeys param must be NULL when calling this function.
@ -94,16 +85,6 @@ LINPHONE_PUBLIC int lime_setCachedKey(xmlDocPtr cacheBuffer, limeKey_t *associat
*/
LINPHONE_PUBLIC void lime_freeKeys(limeURIKeys_t associatedKeys);
/**
* @brief Derive in place the key given in parameter and increment session index
* Derivation is made derived Key = HMAC_SHA256(Key, 0x0000001||"MessageKey"||0x00||SessionId||SessionIndex||256)
*
* @param[in/out] key The structure containing the original key which will be overwritten, the sessionId and SessionIndex
*
* @return 0 on success, error code otherwise
*/
LINPHONE_PUBLIC int lime_deriveKey(limeKey_t *key);
/**
* @brief encrypt a message with the given key
*
@ -196,4 +177,10 @@ LINPHONE_PUBLIC int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t
*/
LINPHONE_PUBLIC char *lime_error_code_to_string(int errorCode);
/**
* @brief Check if Lime was enabled at build time
*
* @return TRUE if Lime is available, FALSE if not
*/
LINPHONE_PUBLIC bool_t lime_is_available();
#endif /* LIME_H */

View file

@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "lpconfig.h"
#include "private.h"
#include "quality_reporting.h"
#include "lime.h"
#include <math.h>
#include <sys/types.h>
@ -1841,7 +1842,7 @@ void linphone_core_enable_lime(LinphoneCore *lc, bool_t val){
}
bool_t linphone_core_lime_enabled(const LinphoneCore *lc){
return lp_config_get_int(lc->config,"sip", "lime", FALSE);
return (lp_config_get_int(lc->config,"sip", "lime", FALSE) && lime_is_available());
}
/**

@ -1 +1 @@
Subproject commit 8e8dd84a37db6d079b254229575b4109973b61a0
Subproject commit d31227221aaf0e1a22af14875563e633396a9086

2
oRTP

@ -1 +1 @@
Subproject commit 19ed314d52d4061a21daa4805aef9459ad31640c
Subproject commit 8eac942e4288e5884267864fc46e641aa5a3c74e

View file

@ -56,7 +56,7 @@ add_definitions(-DBC_CONFIG_FILE="config.h")
add_executable(liblinphone_tester ${SOURCE_FILES})
set_target_properties(liblinphone_tester PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(liblinphone_tester PUBLIC ${CUNIT_INCLUDE_DIRS})
target_include_directories(liblinphone_tester PUBLIC ${CUNIT_INCLUDE_DIRS} PRIVATE common)
target_link_libraries(liblinphone_tester linphone ${CUNIT_LIBRARIES})
if (GTK2_FOUND)
target_compile_definitions(liblinphone_tester PRIVATE HAVE_GTK)

View file

@ -39,7 +39,7 @@ liblinphonetester_la_HEADERS = common/bc_tester_utils.h
liblinphonetester_la_LDFLAGS= -no-undefined
liblinphonetester_la_LIBADD= ../coreapi/liblinphone.la $(CUNIT_LIBS)
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/coreapi
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/coreapi -I$(top_srcdir)/tester/common
AM_CFLAGS = -DBC_CONFIG_FILE=\"config.h\" $(STRICT_OPTIONS) $(STRICT_OPTIONS_CC) -DIN_LINPHONE $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(CUNIT_CFLAGS) $(BELLESIP_CFLAGS) $(LIBXML2_CFLAGS) $(SQLITE3_CFLAGS)
if BUILD_GTK_UI

View file

@ -22,7 +22,7 @@
#include "common/bc_tester_utils.h"
#include "bc_tester_utils.h"
#include "linphonecore.h"
#ifdef HAVE_CONFIG_H
#include "config.h"

View file

@ -572,6 +572,7 @@ static void small_file_transfer_message(void) {
linphone_core_manager_destroy(pauline);
}
#ifdef HAVE_LIME
static void lime_file_transfer_message(void) {
int i;
char *to;
@ -659,6 +660,199 @@ static void lime_file_transfer_message(void) {
}
static void printHex(char *title, uint8_t *data, uint32_t length) {
int i;
printf ("%s : ", title);
for (i=0; i<length; i++) {
printf ("0x%02x, ", data[i]);
}
printf ("\n");
}
static void lime_unit(void) {
int retval;
size_t size;
uint8_t *cacheBufferString;
xmlDocPtr cacheBufferAlice;
xmlDocPtr cacheBufferBob;
uint8_t *multipartMessage = NULL;
uint8_t *decryptedMessage = NULL;
xmlChar *xmlStringOutput;
int xmlStringLength;
limeURIKeys_t associatedKeys;
int i;
limeKey_t associatedKey;
uint8_t targetZID[12] = {0x00, 0x5d, 0xbe, 0x03, 0x99, 0x64, 0x3d, 0x95, 0x3a, 0x22, 0x02, 0xdd};
uint8_t senderZID[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0};
uint8_t encryptedMessage[48];
uint8_t plainMessage[48];
uint8_t receiverZID[12];
xmlDocPtr cacheBuffer;
/* Load Alice cache file */
FILE *CACHE = fopen("ZIDCacheAlice.xml", "rb+");
cacheBufferString = (uint8_t *)ms_load_file_content(CACHE, &size);
*(cacheBufferString+size) = '\0';
fclose(CACHE);
/* parse it to an xmlDoc */
cacheBufferAlice = xmlParseDoc(cacheBufferString);
ms_free(cacheBufferString);
/* Load Bob cache file */
CACHE = fopen("ZIDCacheBob.xml", "rb+");
cacheBufferString = (uint8_t *)ms_load_file_content(CACHE, &size);
*(cacheBufferString+size) = '\0';
fclose(CACHE);
/* parse it to an xmlDoc */
cacheBufferBob = xmlParseDoc(cacheBufferString);
ms_free(cacheBufferString);
/* encrypt a message */
retval = lime_createMultipartMessage(cacheBufferAlice, (uint8_t *)"Bonjour les petits lapins,ca va? éh oui oui", (uint8_t *)"sip:pauline@sip.example.org", &multipartMessage);
printf("create message return %d\n", retval);
if (retval == 0) {
printf("message is %s\n", multipartMessage);
}
/* decrypt the multipart message */
retval = lime_decryptMultipartMessage(cacheBufferBob, multipartMessage, &decryptedMessage);
printf("decrypt message return %d\n", retval);
if (retval == 0) {
printf("message is %s##END\n", decryptedMessage);
}
free(multipartMessage);
free(decryptedMessage);
/* update ZID files */
/* dump the xml document into a string */
xmlDocDumpFormatMemoryEnc(cacheBufferAlice, &xmlStringOutput, &xmlStringLength, "UTF-8", 0);
/* write it to the file */
CACHE = fopen("ZIDCacheAlice.xml", "wb+");
fwrite(xmlStringOutput, 1, xmlStringLength, CACHE);
xmlFree(xmlStringOutput);
fclose(CACHE);
xmlDocDumpFormatMemoryEnc(cacheBufferBob, &xmlStringOutput, &xmlStringLength, "UTF-8", 0);
/* write it to the file */
CACHE = fopen("ZIDCacheBob.xml", "wb+");
fwrite(xmlStringOutput, 1, xmlStringLength, CACHE);
xmlFree(xmlStringOutput);
fclose(CACHE);
xmlFreeDoc(cacheBufferAlice);
xmlFreeDoc(cacheBufferBob);
/* Load cache file */
CACHE = fopen("ZIDCache.xml", "rb+");
cacheBufferString = (uint8_t*) ms_load_file_content(CACHE, &size);
*(cacheBufferString+size) = '\0';
fclose(CACHE);
/* parse it to an xmlDoc */
cacheBuffer = xmlParseDoc(cacheBufferString);
ms_free(cacheBufferString);
/* get data from cache : sender */
associatedKeys.peerURI = (uint8_t *)malloc(15);
memcpy(associatedKeys.peerURI, "pipo1@pipo.com", 15);
associatedKeys.associatedZIDNumber = 0;
retval = lime_getCachedSndKeysByURI(cacheBuffer, &associatedKeys);
printf("getCachedKeys returns %d, number of key found %d\n", retval, associatedKeys.associatedZIDNumber);
for (i=0; i<associatedKeys.associatedZIDNumber; i++) {
printHex("ZID", associatedKeys.peerKeys[i]->peerZID, 12);
printHex("key", associatedKeys.peerKeys[i]->key, 32);
printHex("sessionID", associatedKeys.peerKeys[i]->sessionId, 32);
printf("session index %d\n", associatedKeys.peerKeys[i]->sessionIndex);
}
/* get data from cache : receiver */
memcpy(associatedKey.peerZID, targetZID, 12);
retval = lime_getCachedRcvKeyByZid(cacheBuffer, &associatedKey);
printf("getCachedKey by ZID return %d\n", retval);
printHex("Key", associatedKey.key, 32);
printHex("sessionID", associatedKey.sessionId, 32);
printf("session index %d\n", associatedKey.sessionIndex);
/* encrypt/decrypt a message */
lime_encryptMessage(associatedKeys.peerKeys[0], (uint8_t *)"bla Bla bla b! Pipo", 20, senderZID, encryptedMessage);
printHex("Ciphered", encryptedMessage, 32);
/* invert sender and receiverZID to decrypt/authenticate */
memcpy(receiverZID, associatedKeys.peerKeys[0]->peerZID, 12);
memcpy(associatedKeys.peerKeys[0]->peerZID, senderZID, 12);
retval = lime_decryptMessage(associatedKeys.peerKeys[0], encryptedMessage, 36, receiverZID, plainMessage);
printf("Decrypt and auth returned %d\nPlain: %s\n", retval, plainMessage);
/* update receiver data */
associatedKey.sessionIndex++;
associatedKey.key[0]++;
associatedKey.sessionId[0]++;
retval = lime_setCachedKey(cacheBuffer, &associatedKey, LIME_RECEIVER);
printf("setCachedKey return %d\n", retval);
/* update sender data */
associatedKeys.peerKeys[0]->sessionIndex++;
associatedKeys.peerKeys[0]->key[0]++;
associatedKeys.peerKeys[0]->sessionId[0]++;
retval = lime_setCachedKey(cacheBuffer, associatedKeys.peerKeys[0], LIME_SENDER);
printf("setCachedKey return %d\n", retval);
/* free memory */
lime_freeKeys(associatedKeys);
/* write the file */
/* dump the xml document into a string */
xmlDocDumpFormatMemoryEnc(cacheBuffer, &xmlStringOutput, &xmlStringLength, "UTF-8", 0);
/* write it to the file */
CACHE = fopen("ZIDCache.xml", "w+");
fwrite(xmlStringOutput, 1, xmlStringLength, CACHE);
xmlFree(xmlStringOutput);
fclose(CACHE);
xmlFreeDoc(cacheBuffer);
}
static void lime_text_message(void) {
char* to;
FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD;
LinphoneChatRoom* chat_room;
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
/* make sure lime is enabled */
linphone_core_enable_lime(marie->lc, 1);
linphone_core_enable_lime(pauline->lc, 1);
/* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */
ZIDCacheMarieFD = fopen("tmpZIDCacheMarie.xml", "w");
ZIDCachePaulineFD = fopen("tmpZIDCachePauline.xml", "w");
fprintf(ZIDCacheMarieFD, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>ef7692d0792a67491ae2d44e</selfZID><peer><ZID>005dbe0399643d953a2202dd</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d</sndKey><rcvKey>60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a</rcvKey><sndSId>5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>00000078</sndIndex><rcvIndex>000001cf</rcvIndex><pvs>01</pvs></peer><peer><ZID>1234567889643d953a2202ee</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a9176</sndKey><rcvKey>25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>22ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>0000000f</sndIndex><rcvIndex>00000000</rcvIndex></peer></cache>", linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity));
fprintf(ZIDCachePaulineFD, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>005dbe0399643d953a2202dd</selfZID><peer><ZID>ef7692d0792a67491ae2d44e</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><rcvKey>08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d</rcvKey><sndKey>60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a</sndKey><rcvSId>5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndSId>bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvIndex>00000078</rcvIndex><sndIndex>000001cf</sndIndex><pvs>01</pvs></peer><peer><ZID>1234567889643d953a2202ee</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa</sndKey><rcvKey>25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>22ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>0000002e</sndIndex><rcvIndex>00000000</rcvIndex><pvs>01</pvs></peer></cache>", linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity));
fclose(ZIDCacheMarieFD);
fclose(ZIDCachePaulineFD);
linphone_core_set_zrtp_secrets_file(marie->lc, "tmpZIDCacheMarie.xml");
linphone_core_set_zrtp_secrets_file(pauline->lc, "tmpZIDCachePauline.xml");
to = linphone_address_as_string(marie->identity);
chat_room = linphone_core_create_chat_room(pauline->lc,to);
ms_free(to);
linphone_chat_room_send_message(chat_room,"Bla bla bla bla");
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1);
CU_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity));
/* TODO : check the message arrived correctly deciphered */
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
#endif /* HAVE_LIME */
static void file_transfer_message_io_error_upload(void) {
int i;
char* to;
@ -1128,199 +1322,6 @@ static void is_composing_notification(void) {
linphone_core_manager_destroy(pauline);
}
void printHex(char *title, uint8_t *data, uint32_t length) {
int i;
printf ("%s : ", title);
for (i=0; i<length; i++) {
printf ("0x%02x, ", data[i]);
}
printf ("\n");
}
static void lime_unit(void) {
int retval;
size_t size;
uint8_t *cacheBufferString;
xmlDocPtr cacheBufferAlice;
xmlDocPtr cacheBufferBob;
uint8_t *multipartMessage = NULL;
uint8_t *decryptedMessage = NULL;
xmlChar *xmlStringOutput;
int xmlStringLength;
limeURIKeys_t associatedKeys;
int i;
limeKey_t associatedKey;
uint8_t targetZID[12] = {0x00, 0x5d, 0xbe, 0x03, 0x99, 0x64, 0x3d, 0x95, 0x3a, 0x22, 0x02, 0xdd};
uint8_t senderZID[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0};
uint8_t encryptedMessage[48];
uint8_t plainMessage[48];
uint8_t receiverZID[12];
xmlDocPtr cacheBuffer;
/* Load Alice cache file */
FILE *CACHE = fopen("ZIDCacheAlice.xml", "rb+");
cacheBufferString = (uint8_t *)ms_load_file_content(CACHE, &size);
*(cacheBufferString+size) = '\0';
fclose(CACHE);
/* parse it to an xmlDoc */
cacheBufferAlice = xmlParseDoc(cacheBufferString);
ms_free(cacheBufferString);
/* Load Bob cache file */
CACHE = fopen("ZIDCacheBob.xml", "rb+");
cacheBufferString = (uint8_t *)ms_load_file_content(CACHE, &size);
*(cacheBufferString+size) = '\0';
fclose(CACHE);
/* parse it to an xmlDoc */
cacheBufferBob = xmlParseDoc(cacheBufferString);
ms_free(cacheBufferString);
/* encrypt a message */
retval = lime_createMultipartMessage(cacheBufferAlice, (uint8_t *)"Bonjour les petits lapins,ca va? éh oui oui", (uint8_t *)"sip:pauline@sip.example.org", &multipartMessage);
printf("create message return %d\n", retval);
if (retval == 0) {
printf("message is %s\n", multipartMessage);
}
/* decrypt the multipart message */
retval = lime_decryptMultipartMessage(cacheBufferBob, multipartMessage, &decryptedMessage);
printf("decrypt message return %d\n", retval);
if (retval == 0) {
printf("message is %s##END\n", decryptedMessage);
}
free(multipartMessage);
free(decryptedMessage);
/* update ZID files */
/* dump the xml document into a string */
xmlDocDumpFormatMemoryEnc(cacheBufferAlice, &xmlStringOutput, &xmlStringLength, "UTF-8", 0);
/* write it to the file */
CACHE = fopen("ZIDCacheAlice.xml", "wb+");
fwrite(xmlStringOutput, 1, xmlStringLength, CACHE);
xmlFree(xmlStringOutput);
fclose(CACHE);
xmlDocDumpFormatMemoryEnc(cacheBufferBob, &xmlStringOutput, &xmlStringLength, "UTF-8", 0);
/* write it to the file */
CACHE = fopen("ZIDCacheBob.xml", "wb+");
fwrite(xmlStringOutput, 1, xmlStringLength, CACHE);
xmlFree(xmlStringOutput);
fclose(CACHE);
xmlFreeDoc(cacheBufferAlice);
xmlFreeDoc(cacheBufferBob);
/* Load cache file */
CACHE = fopen("ZIDCache.xml", "rb+");
cacheBufferString = (uint8_t*) ms_load_file_content(CACHE, &size);
*(cacheBufferString+size) = '\0';
fclose(CACHE);
/* parse it to an xmlDoc */
cacheBuffer = xmlParseDoc(cacheBufferString);
ms_free(cacheBufferString);
/* get data from cache : sender */
associatedKeys.peerURI = (uint8_t *)malloc(15);
memcpy(associatedKeys.peerURI, "pipo1@pipo.com", 15);
associatedKeys.associatedZIDNumber = 0;
retval = lime_getCachedSndKeysByURI(cacheBuffer, &associatedKeys);
printf("getCachedKeys returns %d, number of key found %d\n", retval, associatedKeys.associatedZIDNumber);
for (i=0; i<associatedKeys.associatedZIDNumber; i++) {
printHex("ZID", associatedKeys.peerKeys[i]->peerZID, 12);
printHex("key", associatedKeys.peerKeys[i]->key, 32);
printHex("sessionID", associatedKeys.peerKeys[i]->sessionId, 32);
printf("session index %d\n", associatedKeys.peerKeys[i]->sessionIndex);
}
/* get data from cache : receiver */
memcpy(associatedKey.peerZID, targetZID, 12);
retval = lime_getCachedRcvKeyByZid(cacheBuffer, &associatedKey);
printf("getCachedKey by ZID return %d\n", retval);
printHex("Key", associatedKey.key, 32);
printHex("sessionID", associatedKey.sessionId, 32);
printf("session index %d\n", associatedKey.sessionIndex);
/* encrypt/decrypt a message */
lime_encryptMessage(associatedKeys.peerKeys[0], (uint8_t *)"bla Bla bla b! Pipo", 20, senderZID, encryptedMessage);
printHex("Ciphered", encryptedMessage, 32);
/* invert sender and receiverZID to decrypt/authenticate */
memcpy(receiverZID, associatedKeys.peerKeys[0]->peerZID, 12);
memcpy(associatedKeys.peerKeys[0]->peerZID, senderZID, 12);
retval = lime_decryptMessage(associatedKeys.peerKeys[0], encryptedMessage, 36, receiverZID, plainMessage);
printf("Decrypt and auth returned %d\nPlain: %s\n", retval, plainMessage);
/* update receiver data */
associatedKey.sessionIndex++;
associatedKey.key[0]++;
associatedKey.sessionId[0]++;
retval = lime_setCachedKey(cacheBuffer, &associatedKey, LIME_RECEIVER);
printf("setCachedKey return %d\n", retval);
/* update sender data */
associatedKeys.peerKeys[0]->sessionIndex++;
associatedKeys.peerKeys[0]->key[0]++;
associatedKeys.peerKeys[0]->sessionId[0]++;
retval = lime_setCachedKey(cacheBuffer, associatedKeys.peerKeys[0], LIME_SENDER);
printf("setCachedKey return %d\n", retval);
/* free memory */
lime_freeKeys(associatedKeys);
/* write the file */
/* dump the xml document into a string */
xmlDocDumpFormatMemoryEnc(cacheBuffer, &xmlStringOutput, &xmlStringLength, "UTF-8", 0);
/* write it to the file */
CACHE = fopen("ZIDCache.xml", "w+");
fwrite(xmlStringOutput, 1, xmlStringLength, CACHE);
xmlFree(xmlStringOutput);
fclose(CACHE);
xmlFreeDoc(cacheBuffer);
}
static void lime_text_message(void) {
char* to;
FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD;
LinphoneChatRoom* chat_room;
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
/* make sure lime is enabled */
linphone_core_enable_lime(marie->lc, 1);
linphone_core_enable_lime(pauline->lc, 1);
/* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */
ZIDCacheMarieFD = fopen("tmpZIDCacheMarie.xml", "w");
ZIDCachePaulineFD = fopen("tmpZIDCachePauline.xml", "w");
fprintf(ZIDCacheMarieFD, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>ef7692d0792a67491ae2d44e</selfZID><peer><ZID>005dbe0399643d953a2202dd</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d</sndKey><rcvKey>60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a</rcvKey><sndSId>5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>00000078</sndIndex><rcvIndex>000001cf</rcvIndex><pvs>01</pvs></peer><peer><ZID>1234567889643d953a2202ee</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a9176</sndKey><rcvKey>25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>22ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>0000000f</sndIndex><rcvIndex>00000000</rcvIndex></peer></cache>", linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity));
fprintf(ZIDCachePaulineFD, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>005dbe0399643d953a2202dd</selfZID><peer><ZID>ef7692d0792a67491ae2d44e</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><rcvKey>08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d</rcvKey><sndKey>60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a</sndKey><rcvSId>5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndSId>bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvIndex>00000078</rcvIndex><sndIndex>000001cf</sndIndex><pvs>01</pvs></peer><peer><ZID>1234567889643d953a2202ee</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa</sndKey><rcvKey>25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>22ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>0000002e</sndIndex><rcvIndex>00000000</rcvIndex><pvs>01</pvs></peer></cache>", linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity));
fclose(ZIDCacheMarieFD);
fclose(ZIDCachePaulineFD);
linphone_core_set_zrtp_secrets_file(marie->lc, "tmpZIDCacheMarie.xml");
linphone_core_set_zrtp_secrets_file(pauline->lc, "tmpZIDCachePauline.xml");
to = linphone_address_as_string(marie->identity);
chat_room = linphone_core_create_chat_room(pauline->lc,to);
ms_free(to);
linphone_chat_room_send_message(chat_room,"Bla bla bla bla");
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1);
CU_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity));
/* TODO : check the message arrived correctly deciphered */
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
#ifdef MSG_STORAGE_ENABLED
/*
@ -1519,7 +1520,6 @@ static void history_messages_count() {
#endif
test_t message_tests[] = {
{ "Lime Text Message", lime_text_message },
{ "Text message", text_message },
{ "Text message within call's dialog", text_message_within_dialog},
{ "Text message with credentials from auth info cb", text_message_with_credential_from_auth_cb},
@ -1534,13 +1534,16 @@ test_t message_tests[] = {
/* { "File transfer message with io error at download", file_transfer_message_io_error_download },*/
{ "File transfer message upload cancelled", file_transfer_message_upload_cancelled },
{ "File transfer message download cancelled", file_transfer_message_download_cancelled },
{ "Lime File transfer message", lime_file_transfer_message },
{ "File transfer message using external body url", file_transfer_using_external_body_url },
{ "Text message denied", text_message_denied },
{ "Info message", info_message },
{ "Info message with body", info_message_with_body },
{ "IsComposing notification", is_composing_notification },
{ "Lime Unitary", lime_unit }
{ "IsComposing notification", is_composing_notification }
#ifdef HAVE_LIME
,{ "Lime Text Message", lime_text_message }
,{ "Lime File transfer message", lime_file_transfer_message }
,{ "Lime Unitary", lime_unit }
#endif /* HAVE_LIME */
#ifdef MSG_STORAGE_ENABLED
,{ "Database migration", message_storage_migration }
,{ "History count", history_messages_count }

View file

@ -394,10 +394,101 @@ static void early_media_video_with_inactive_audio(void) {
linphone_core_manager_destroy(pauline);
}
static void forked_outgoing_early_media_video_call_with_inactive_audio_test(void) {
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
LinphoneCoreManager *marie1 = linphone_core_manager_new("marie_early_rc");
LinphoneCoreManager *marie2 = linphone_core_manager_new("marie_early_rc");
MSList *lcs = NULL;
LinphoneCallParams *pauline_params;
LinphoneCallParams *marie1_params;
LinphoneCallParams *marie2_params;
LinphoneVideoPolicy pol;
LinphoneCall *marie1_call;
LinphoneCall *marie2_call;
LinphoneCall *pauline_call;
LinphoneInfoMessage *info;
int dummy = 0;
pol.automatically_accept = 1;
pol.automatically_initiate = 1;
linphone_core_enable_video(pauline->lc, TRUE, TRUE);
linphone_core_enable_video(marie1->lc, TRUE, TRUE);
linphone_core_set_video_policy(marie1->lc, &pol);
linphone_core_enable_video(marie2->lc, TRUE, TRUE);
linphone_core_set_video_policy(marie2->lc, &pol);
linphone_core_set_audio_port_range(marie2->lc, 40200, 40300);
linphone_core_set_video_port_range(marie2->lc, 40400, 40500);
lcs = ms_list_append(lcs,marie1->lc);
lcs = ms_list_append(lcs,marie2->lc);
lcs = ms_list_append(lcs,pauline->lc);
pauline_params = linphone_core_create_default_call_parameters(pauline->lc);
linphone_call_params_enable_early_media_sending(pauline_params, TRUE);
linphone_call_params_enable_video(pauline_params, TRUE);
marie1_params = configure_for_early_media_video_receiving_with_inactive_audio(marie1);
marie2_params = configure_for_early_media_video_receiving_with_inactive_audio(marie2);
linphone_core_invite_address_with_params(pauline->lc, marie1->identity, pauline_params);
linphone_call_params_destroy(pauline_params);
CU_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallIncomingEarlyMedia, 1, 3000));
CU_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallIncomingEarlyMedia, 1, 3000));
CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia, 1, 3000));
pauline_call = linphone_core_get_current_call(pauline->lc);
marie1_call = linphone_core_get_current_call(marie1->lc);
marie2_call = linphone_core_get_current_call(marie2->lc);
CU_ASSERT_PTR_NOT_NULL(pauline_call);
CU_ASSERT_PTR_NOT_NULL(marie1_call);
CU_ASSERT_PTR_NOT_NULL(marie2_call);
if (pauline_call && marie1_call && marie2_call) {
/* wait a bit that streams are established */
wait_for_list(lcs, &dummy, 1, 6000);
CU_ASSERT_TRUE(linphone_call_get_audio_stats(pauline_call)->download_bandwidth == 0);
CU_ASSERT_TRUE(linphone_call_get_audio_stats(marie1_call)->download_bandwidth == 0);
CU_ASSERT_TRUE(linphone_call_get_audio_stats(marie2_call)->download_bandwidth == 0);
linphone_call_params_set_audio_direction(marie1_params, LinphoneMediaDirectionSendRecv);
linphone_core_accept_call_with_params(marie1->lc, linphone_core_get_current_call(marie1->lc), marie1_params);
CU_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallStreamsRunning, 1, 3000));
CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1, 3000));
/* marie2 should get her call terminated */
CU_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallEnd, 1, 1000));
/*wait a bit that streams are established*/
wait_for_list(lcs, &dummy, 1, 3000);
CU_ASSERT_TRUE(linphone_call_get_audio_stats(pauline_call)->download_bandwidth > 71);
CU_ASSERT_TRUE(linphone_call_get_audio_stats(marie1_call)->download_bandwidth > 71);
CU_ASSERT_TRUE(linphone_call_get_video_stats(pauline_call)->download_bandwidth > 0);
CU_ASSERT_TRUE(linphone_call_get_video_stats(marie1_call)->download_bandwidth > 0);
/* send an INFO in reverse side to check that dialogs are properly established */
info = linphone_core_create_info_message(marie1->lc);
linphone_call_send_info_message(marie1_call, info);
CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_inforeceived, 1, 3000));
}
linphone_core_terminate_all_calls(pauline->lc);
CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallEnd, 1, 3000));
CU_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallEnd, 1, 3000));
linphone_call_params_destroy(marie1_params);
linphone_call_params_destroy(marie2_params);
ms_list_free(lcs);
linphone_core_manager_destroy(marie1);
linphone_core_manager_destroy(marie2);
linphone_core_manager_destroy(pauline);
}
test_t video_tests[] = {
{ "Early-media video during video call", early_media_video_during_video_call_test },
{ "Two incoming early-media video calls", two_incoming_early_media_video_calls_test },
{ "Early-media video with inactive audio", early_media_video_with_inactive_audio }
{ "Early-media video with inactive audio", early_media_video_with_inactive_audio },
{ "Forked outgoing early-media video call with inactive audio", forked_outgoing_early_media_video_call_with_inactive_audio_test }
};
test_suite_t video_test_suite = {