Commit 8f448c3f authored by Sylvain Berfini's avatar Sylvain Berfini 🐮
Browse files

Merge branch 'release/4.4' into tmp/rebase

parents 72b11fef 8b33f937
......@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
This changelog file was started on October 2019. Previous changes were more or less tracked in the *NEWS* file.
## [Unreleased]
### Added
- RTP bundle mode feature according to https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54 .
- EnterForeground and enterBackground automatically for ios and anroid.
......@@ -19,9 +19,6 @@ This changelog file was started on October 2019. Previous changes were more or l
- Added API to play user's ringtone instead of default ringtone for Android.
### Changed
- Big internal refactoring of how streams are managed within offer/answer exchanges.
- ICE now uses all IP addresses detected on the host.
- Better handling of parameter changes in streams during the session, which avoids unecessary restarts.
- Improved Android network manager.
### Fixed
......@@ -30,6 +27,36 @@ This changelog file was started on October 2019. Previous changes were more or l
- Error IMDN in LIME chat rooms not properly sent.
- Chat message lost during attachment auto download if Core stopped during the process.
## [4.4.0] 2020-06-16
### Added
- Simplified integration with CallKit, see https://wiki.linphone.org/xwiki/wiki/public/view/Lib/Getting%20started/iOS/#HCallKitIntegration
- Specific additions to take into account new iOS 13 constraints, see https://wiki.linphone.org/xwiki/wiki/public/view/Lib/Getting%20started/iOS/iOS13%20Migration%20guide/
* compatibility for inclusion within an app extension
* helper functions to create a LinphoneCore that can be shared between an app and its extension
* helper functions to process remote push notifications announcing IM messages
- RTP bundle mode feature according to https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54, providing
increased interoperability with WebRTC.
- TURN over TCP or TLS
- Ephemeral IM - let user program automatic destruction of IM messages.
- SIP Session-Timers (RFC4028)
- New method linphone_core_stop_async(), to ensure clean shutdown can be done without blocking main thread.
### Changed
- Big internal refactoring of how streams are managed within offer/answer exchanges, in order to facilitate bundle mode
implementation, as well as development of new features.
- ICE now uses all IP addresses detected on the host (except IPv6 temporary ones)
- Better handling of parameter changes in streams during the session, which avoids unecessary restarts.
- Do not notify phone number being too short in account manager anymore, our dial plan isn't precise enough to garanty phone number is invalid in this case
- Swift wrapper is no longer compiled due to its limited binary compatibility. It is instead exported as source code to be compiled with
the application making use of it.
### Fixed
- Internal refactoring of management of locally played tones, in order to fix race conditions.
- Issues when handling SDP offer with only text stream.
- Random file transfer issues when used with LIME.
## [4.3.0] - 2019-10-14
### Added
......
......@@ -28,7 +28,7 @@ set(LINPHONE_MAJOR_VERSION ${PROJECT_VERSION_MAJOR})
set(LINPHONE_MINOR_VERSION ${PROJECT_VERSION_MINOR})
set(LINPHONE_MICRO_VERSION ${PROJECT_VERSION_PATCH})
set(LINPHONE_VERSION ${PROJECT_VERSION})
set(LINPHONE_SO_VERSION "9")
set(LINPHONE_SO_VERSION "10") #incremented for 4.4.0 release.
file(GLOB LINPHONE_PO_FILES RELATIVE "${CMAKE_CURRENT_LIST_DIR}/po" "${CMAKE_CURRENT_LIST_DIR}/po/*.po")
string(REGEX REPLACE "([a-zA-Z_]+)\\.po" "\\1" LINPHONE_ALL_LANGS_LIST "${LINPHONE_PO_FILES}")
......
......@@ -505,10 +505,13 @@ LinphoneAccountCreatorPhoneNumberStatusMask linphone_account_creator_set_phone_n
if (plan->isGeneric()) {
return_status = LinphoneAccountCreatorPhoneNumberStatusInvalidCountryCode;
}
if (size < plan->getNationalNumberLength() - 1) {
// DO NOT NOTIFY ABOUT PHONE NUMBER BEING TOO SHORT,
// OUR DIAL PLAN IMPLEMENTATION ISNT PRECISE ENOUGH TO GARANTY
// THE PHONE NUMBER IS INVALID
/*if (size < plan->getNationalNumberLength() - 1) {
return_status = LinphoneAccountCreatorPhoneNumberStatusTooShort;
goto end;
} else if (size > plan->getNationalNumberLength() + 1) {
} else*/ if (size > plan->getNationalNumberLength() + 1) {
return_status = LinphoneAccountCreatorPhoneNumberStatusTooLong;
goto end;
} else if (return_status & LinphoneAccountCreatorPhoneNumberStatusInvalidCountryCode) {
......
......@@ -1073,7 +1073,8 @@ void linphone_friend_list_update_subscriptions(LinphoneFriendList *list) {
if (address)
cfg = linphone_core_lookup_known_proxy(list->lc, address);
only_when_registered = linphone_core_should_subscribe_friends_only_when_registered(list->lc);
should_send_list_subscribe = (!only_when_registered || !cfg || cfg->state == LinphoneRegistrationOk);
//in case of only_when_registered, proxy config is mandatory to send subscribes. Otherwise, unexpected subscribtion can be issued using default contact address even if no account is configured yet.
should_send_list_subscribe = (!only_when_registered || (cfg && cfg->state == LinphoneRegistrationOk));
}
if (address != NULL) {
......
......@@ -641,10 +641,10 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){
ms_free(from);
} else {
/* unregister if registered*/
_linphone_proxy_config_unregister(cfg);
if (cfg->state == LinphoneRegistrationProgress) {
linphone_proxy_config_set_state(cfg,LinphoneRegistrationCleared,"Registration cleared");
}
_linphone_proxy_config_unregister(cfg);
}
}
......
......@@ -57,17 +57,10 @@ void ChatRoomPrivate::sendChatMessage (const shared_ptr<ChatMessage> &chatMessag
//if not using cpim, ImdnMessageId = SIP Message call id, so should be computed each time, specially in case of resend.
dChatMessage->setImdnMessageId("");
}
dChatMessage->send();
}
void ChatRoomPrivate::onChatMessageSent(const shared_ptr<ChatMessage> &chatMessage) {
L_Q();
ChatMessagePrivate *dChatMessage = chatMessage->getPrivate();
LinphoneChatRoom *cr = getCChatRoom();
// TODO: server currently don't stock message, remove condition in the future.
if (!linphone_core_conference_server_enabled(q->getCore()->getCCore())) {
bool isResend = chatMessage->getState() == ChatMessage::State::NotDelivered;
if (!isResend && !linphone_core_conference_server_enabled(q->getCore()->getCCore())) {
shared_ptr<ConferenceChatMessageEvent> event = static_pointer_cast<ConferenceChatMessageEvent>(
q->getCore()->getPrivate()->mainDb->getEventFromKey(dChatMessage->dbKey)
);
......@@ -79,6 +72,10 @@ void ChatRoomPrivate::onChatMessageSent(const shared_ptr<ChatMessage> &chatMessa
linphone_core_notify_message_sent(q->getCore()->getCCore(), cr, L_GET_C_BACK_PTR(chatMessage));
}
dChatMessage->send();
}
void ChatRoomPrivate::onChatMessageSent(const shared_ptr<ChatMessage> &chatMessage) {
if (isComposing) isComposing = false;
isComposingHandler->stopIdleTimer();
isComposingHandler->stopRefreshTimer();
......@@ -315,7 +312,16 @@ LinphoneReason ChatRoomPrivate::onSipMessageReceived (SalOp *op, const SalMessag
msg->setInternalContent(content);
msg->getPrivate()->setTime(message->time);
msg->getPrivate()->setImdnMessageId(op->getCallId());
ostringstream messageId;
if (op->hasDialog()){
/* If this message has been received part of a dialog (which is unlikely to happen for IM),
* set an IMDN Message ID abitrary to be the SIP Call-ID followed by the CSeq number.
* This avoids considering incoming SIP MESSAGE received within a dialog as being duplicates. */
messageId << op->getCallId() << "-" << op->getRemoteCSeq();
}else{
messageId << op->getCallId();
}
msg->getPrivate()->setImdnMessageId(messageId.str());
msg->getPrivate()->setCallId(op->getCallId());
const SalCustomHeader *ch = op->getRecvCustomHeaders();
......
......@@ -379,6 +379,12 @@ ChatRoom::SecurityLevel ClientGroupChatRoom::getSecurityLevel () const {
if (!(d->capabilities & ClientGroupChatRoom::Capabilities::Encrypted)) {
return AbstractChatRoom::SecurityLevel::ClearText;
}
// Until participant list & self devices list is populated, don't assume chat room is safe but encrypted
if (getParticipants().size() == 0 && getMe()->getPrivate()->getDevices().size() == 0) {
lInfo() << "Chatroom SecurityLevel = Encrypted";
return AbstractChatRoom::SecurityLevel::Encrypted;
}
bool isSafe = true;
// check other participants
......
......@@ -90,10 +90,6 @@ void RealTimeTextChatRoomPrivate::sendChatMessage (const shared_ptr<ChatMessage>
uint32_t newLine = 0x2028;
chatMessage->putCharacter(newLine);
}
}
void RealTimeTextChatRoomPrivate::onChatMessageSent(const shared_ptr<ChatMessage> &chatMessage) {
L_Q();
ChatMessagePrivate *dChatMessage = chatMessage->getPrivate();
shared_ptr<ConferenceChatMessageEvent> event = static_pointer_cast<ConferenceChatMessageEvent>(
......@@ -105,6 +101,10 @@ void RealTimeTextChatRoomPrivate::onChatMessageSent(const shared_ptr<ChatMessage
_linphone_chat_room_notify_chat_message_sent(cr, L_GET_C_BACK_PTR(event));
}
void RealTimeTextChatRoomPrivate::onChatMessageSent(const shared_ptr<ChatMessage> &chatMessage) {
}
// =============================================================================
RealTimeTextChatRoom::RealTimeTextChatRoom (const shared_ptr<Core> &core, const ConferenceId &conferenceId, const std::shared_ptr<ChatRoomParams> &params) :
......
......@@ -355,6 +355,12 @@ bool MS2Stream::handleBasicChanges(const OfferAnswerContext &params, CallSession
return true;
}
if (getState() == Stream::Running){
if (getMediaSessionPrivate().getCurrentParams()->getPrivate()->getInConference() != getMediaSessionPrivate().getParams()->getPrivate()->getInConference()){
lInfo() << "Stream needs to be restarted because of a change in its conference membership attribute.";
lInfo() << "Will become joined to a conference: " << (getMediaSessionPrivate().getParams()->getPrivate()->getInConference() ? "yes" : "no");
stop();
return false;
}
int changesToHandle = params.resultStreamDescriptionChanges;
if (params.resultStreamDescriptionChanges & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED){
updateDestinations(params);
......
......@@ -397,7 +397,7 @@ void IosPlatformHelpers::stopNetworkMonitoring(void) {
CFRelease(reachabilityRef);
reachabilityRef = NULL;
}
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (void *) this, CFSTR("com.apple.system.config.network_change"), NULL);
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (void *) this, CFSTR(kNotifySCNetworkChange), NULL);
}
//This callback keeps tracks of wifi SSID changes
......@@ -406,8 +406,8 @@ static void sNetworkChangeCallback(CFNotificationCenterRef center, void *observe
return;
}
IosPlatformHelpers *iosHelper = (IosPlatformHelpers *) observer;
//Important: actual actions on core and possibly on UI are to be taken from main thread
dispatch_async(dispatch_get_main_queue(), ^{
iosHelper->getCore()->doLater([iosHelper] () {
iosHelper->networkChangeCallback();
});
}
......
......@@ -212,7 +212,7 @@ static void on_push_notification_message_received(LinphoneCore *lc, LinphoneChat
void IosSharedCoreHelpers::registerSharedCoreMsgCallback() {
if (isCoreShared()) {
lInfo() << "[push] register main core msg callback";
lInfo() << "[push] register shared core msg callback";
LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
linphone_core_cbs_set_message_received(cbs, on_push_notification_message_received);
linphone_core_add_callbacks(getCore()->getCCore(), cbs);
......@@ -221,6 +221,10 @@ void IosSharedCoreHelpers::registerSharedCoreMsgCallback() {
}
void IosSharedCoreHelpers::onLinphoneCoreStop() {
lInfo() << "[SHARED] " << __FUNCTION__;
CFNotificationCenterRef notification = CFNotificationCenterGetDarwinNotifyCenter();
CFNotificationCenterRemoveObserver(notification, (__bridge const void *)(this), CFSTR(ACTIVE_SHARED_CORE), NULL);
if (isCoreShared()) {
CFRunLoopTimerInvalidate(mUnlockTimer);
lInfo() << "[SHARED] stop timer";
......@@ -698,8 +702,13 @@ void IosSharedCoreHelpers::setSharedCoreState(SharedCoreState sharedCoreState) {
}
void IosSharedCoreHelpers::setSharedCoreState(SharedCoreState sharedCoreState, const string &appGroupId) {
userDefaultMutex.lock();
lInfo() << "[SHARED] setSharedCoreState state: " << sharedStateToString(sharedCoreState);
if (appGroupId.empty()) {
lInfo() << "[SHARED] unable to setSharedCoreState state: appGroupId empty";
return;
}
userDefaultMutex.lock();
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@(appGroupId.c_str())];
[defaults setInteger:sharedCoreState forKey:@ACTIVE_SHARED_CORE];
[defaults release];
......@@ -789,7 +798,9 @@ void on_core_must_stop(CFNotificationCenterRef center, void *observer, CFStringR
void IosSharedCoreHelpers::onCoreMustStop() {
lInfo() << "[SHARED] " << __FUNCTION__;
setSharedCoreState(SharedCoreState::executorCoreStopping);
if (getSharedCoreState() != SharedCoreState::executorCoreStopping) {
setSharedCoreState(SharedCoreState::executorCoreStopping);
}
}
// -----------------------------------------------------------------------------
......
......@@ -1771,6 +1771,16 @@ void MainDbPrivate::importLegacyHistory (DbSession &inDbSession) {
"ORDER BY conference_event.event_id DESC LIMIT 1) "// Ensure to have only one event and the last id for the matching time
"WHERE id = :1 ", soci::use(chatRoomId);// Used to not get Empty chatroom
}
// Set last_message_id to the last timed message for all chat room
*dbSession.getBackendSession() << "UPDATE chat_room SET last_message_id = "
"(SELECT COALESCE( (SELECT max(conference_event.event_id) as m "// max(conference_event.event_id) ensure to have only one event and the last id for the matching time
"FROM conference_event, conference_chat_message_event,"
"(SELECT max(time) as t, conference_event.chat_room_id as c "// Get Max Time for the chat room
"FROM conference_event, conference_chat_message_event "
"WHERE conference_event.event_id=conference_chat_message_event.event_id GROUP BY conference_event.chat_room_id)"
"WHERE conference_chat_message_event.time=t AND conference_chat_message_event.event_id=conference_event.event_id AND conference_event.chat_room_id=c "
"AND conference_event.chat_room_id=chat_room.id "
"GROUP BY conference_event.chat_room_id),0))";// if there are no messages, the first is NULL. So put a 0 to the ID
tr.commit();
lInfo() << "Successful import of legacy messages.";
};
......
......@@ -1091,4 +1091,9 @@ void SalOp::setServiceRoute(const SalAddress *value) {
mServiceRoute = value ? sal_address_clone(value) : nullptr;
}
unsigned int SalOp::getRemoteCSeq(){
if (mDialog) return belle_sip_dialog_get_remote_seq_number(mDialog);
return 0;
}
LINPHONE_END_NAMESPACE
......@@ -122,7 +122,10 @@ public:
belle_sip_refresher_stop(mRefresher);
}
int refresh ();
void killDialog ();
bool hasDialog() const{ return mDialog != nullptr; };
void killDialog();
// Returns the remote CSeq, only in case the op has a dialog.
unsigned int getRemoteCSeq();
//Release means let the op finish its life but we don't want to use it anymore, and don't want to be called in callbacks for this op
void release ();
......
......@@ -36,6 +36,7 @@ int SalRegisterOp::sendRegister (const string &proxy, const string &from, int ex
setTo(from);
setRoute(proxy);
auto request = buildRequest("REGISTER");
if (request == nullptr) return -1;
auto requestUri = belle_sip_request_get_uri(request);
belle_sip_uri_set_user(requestUri, nullptr); // Remove userinfo if there is any
if (mRoot->mUseDates) {
......
......@@ -252,7 +252,7 @@ static void local_email_ok(void) {
////// PHONE NUMBER //////
static void local_phone_number_too_short(void) {
/*static void local_phone_number_too_short(void) {
LinphoneCoreManager *marie = linphone_core_manager_new2("account_creator_rc", 0);
LinphoneAccountCreator *creator = _linphone_account_creator_new(marie->lc, "");
......@@ -264,7 +264,7 @@ static void local_phone_number_too_short(void) {
linphone_account_creator_unref(creator);
linphone_core_manager_destroy(marie);
}
}*/
static void local_phone_number_too_long(void) {
LinphoneCoreManager *marie = linphone_core_manager_new2("account_creator_rc", 0);
......@@ -979,7 +979,6 @@ static void server_create_account_with_phone_number_arg_username_missing(void) {
LinphoneAccountCreatorCbs *cbs = linphone_account_creator_get_callbacks(creator);
LinphoneAccountCreatorStats *stats = new_linphone_account_creator_stats();
linphone_account_creator_set_phone_number(creator, "0123456", "33");
linphone_account_creator_set_password(creator, "password");
linphone_account_creator_cbs_set_user_data(cbs, stats);
......@@ -1302,7 +1301,6 @@ static void server_activate_account_with_phone_number_activated_arg_username_mis
LinphoneAccountCreatorStats *stats = new_linphone_account_creator_stats();
linphone_account_creator_set_activation_code(creator, "123456789");
linphone_account_creator_set_phone_number(creator, "0123456", "33");
linphone_account_creator_cbs_set_user_data(cbs, stats);
linphone_account_creator_service_set_user_data(
......@@ -2037,7 +2035,6 @@ static void server_update_account_password_arg_username_missing(void) {
LinphoneAccountCreatorCbs *cbs = linphone_account_creator_get_callbacks(creator);
LinphoneAccountCreatorStats *stats = new_linphone_account_creator_stats();
linphone_account_creator_set_phone_number(creator, "0123456", "33");
linphone_account_creator_set_password(creator, "password");
linphone_account_creator_set_user_data(creator, "newpassword");
......@@ -2404,10 +2401,10 @@ test_t account_creator_tests[] = {
"Local - Email Ok",
local_email_ok,
"Local"),
TEST_ONE_TAG(
/*TEST_ONE_TAG(
"Local - Phone number too short",
local_phone_number_too_short,
"Local"),
"Local"),*/
TEST_ONE_TAG(
"Local - Phone number too long",
local_phone_number_too_long,
......
......@@ -542,9 +542,6 @@ static void _simple_conference_from_scratch(bool_t with_video){
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(laure);
bctbx_list_free(participants);
bctbx_list_free(lcs);
}
static void simple_conference_from_scratch(void){
......@@ -574,7 +571,8 @@ static void video_conference_by_merging_calls(void){
linphone_core_set_play_file(pauline->lc, play_file_pauline);
bc_free(play_file_pauline);
participants = bctbx_list_append(participants, pauline->identity);
bctbx_list_free(participants);
bctbx_list_free(lcs);participants = bctbx_list_append(participants, pauline->identity);
participants = bctbx_list_append(participants, laure->identity);
{
......@@ -703,6 +701,85 @@ end:
bctbx_list_free(lcs);
}
static void simple_conference_from_scratch_no_answer(void){
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
LinphoneCoreManager* laure = linphone_core_manager_new( get_laure_rc());
LinphoneConference *conf;
LinphoneConferenceParams *conf_params;
LinphoneCall *pauline_call, *laure_call;
bctbx_list_t *participants = NULL;
bctbx_list_t *lcs = NULL;
lcs = bctbx_list_append(lcs, marie->lc);
lcs = bctbx_list_append(lcs, pauline->lc);
lcs = bctbx_list_append(lcs, laure->lc);
/*marie creates the conference*/
conf_params = linphone_core_create_conference_params(marie->lc);
linphone_conference_params_enable_video(conf_params, FALSE);
conf = linphone_core_create_conference_with_params(marie->lc, conf_params);
linphone_conference_params_unref(conf_params);
participants = bctbx_list_append(participants, pauline->identity);
participants = bctbx_list_append(participants, laure->identity);
linphone_conference_invite_participants(conf, participants, NULL);
linphone_conference_unref(conf);
lcs = bctbx_list_remove(lcs, laure->lc);
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingProgress,1,2000));
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallIncomingReceived,1,10000));
pauline_call = linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
if (pauline_call){
pauline_call = linphone_core_get_current_call(pauline->lc);
/* Pauline immediately declines the call.*/
linphone_call_decline(pauline_call, LinphoneReasonDeclined);
}
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,5000));
wait_for_list(lcs,NULL,0,1000);
lcs = bctbx_list_append(lcs, laure->lc);
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallIncomingReceived,1,10000));
laure_call = linphone_core_get_current_call(laure->lc);
BC_ASSERT_PTR_NOT_NULL(laure_call);
if ( laure_call){
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingRinging,2,2000));
wait_for_list(lcs,NULL,0,1000);
/* Laure accepts. */
linphone_call_accept(laure_call);
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallStreamsRunning,1,10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,5000));
wait_for_list(lcs,NULL,0,1000);
/* the conference no longer exists, as there was finally only one participant.
* Terminate the call, simply.*/
linphone_call_terminate(laure_call);
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallEnd,1,10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,2,5000));
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallReleased,2,1000));
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallReleased,1,1000));
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallReleased,1,1000));
}
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(laure);
bctbx_list_free(participants);
bctbx_list_free(lcs);
}
static void simple_encrypted_conference_with_ice(LinphoneMediaEncryption mode) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
......@@ -1237,9 +1314,11 @@ static void eject_from_4_participants_conference(void) {
linphone_core_add_to_conference(marie->lc,marie_call_michelle);
linphone_core_add_to_conference(marie->lc,marie_call_pauline);
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallStreamsRunning, 2,10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning, 2,10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&michelle->stat.number_of_LinphoneCallStreamsRunning, 2,10000));
/* Wait that the three participants are joined to the local conference, by checking the StreamsRunning states*/
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallStreamsRunning, 2, 10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&michelle->stat.number_of_LinphoneCallStreamsRunning, 2, 10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning, 2, 10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning, 6, 10000));
BC_ASSERT_TRUE(linphone_core_is_in_conference(marie->lc));
BC_ASSERT_EQUAL(linphone_core_get_conference_size(marie->lc),4, int, "%d");
......@@ -1904,6 +1983,7 @@ test_t multi_call_tests[] = {
TEST_NO_TAG("Simple conference established from scratch", simple_conference_from_scratch),
TEST_NO_TAG("Simple conference established from scratch with video", simple_conference_from_scratch_with_video),
TEST_NO_TAG("Video conference by merging calls", video_conference_by_merging_calls),
TEST_NO_TAG("Simple conference established from scratch, but attendees do not answer", simple_conference_from_scratch_no_answer),
TEST_ONE_TAG("Simple conference with ICE", simple_conference_with_ice, "ICE"),
TEST_ONE_TAG("Simple ZRTP conference with ICE", simple_zrtp_conference_with_ice, "ICE"),
TEST_NO_TAG("Simple conference with audio device change during setup", simple_conference_with_audio_device_change_during_setup),
......
......@@ -429,8 +429,10 @@ LinphoneChatRoom * create_chat_room_client_side_with_expected_number_of_particip
if (!chatRoom) return NULL;
BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomStateInstantiated, initialStats->number_of_LinphoneChatRoomStateInstantiated + 1, 100));
if (encrypted)
if (encrypted) {
BC_ASSERT_EQUAL(linphone_chat_room_get_security_level(chatRoom), LinphoneChatRoomSecurityLevelEncrypted, LinphoneChatRoomSecurityLevel, "%i");
BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(chatRoom) & LinphoneChatRoomCapabilitiesEncrypted);
}
// Check that the chat room is correctly created on Marie's side and that the participants are added
BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomStateCreationPending, initialStats->number_of_LinphoneChatRoomStateCreationPending + 1, 5000));
......
......@@ -250,6 +250,12 @@ static void text_message_within_call_dialog(void) {
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
// when using call dialogs, we will never receive delivered status
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,0,int,"%d");
// Send a second message, so that we can check that it is not erroneously filtered out because
// it bears the same call-id.
linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc, marie->identity),"Bouhbouhbouh");
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,2));
end_call(marie, pauline);
}
......@@ -754,7 +760,7 @@ static void transfer_message_with_download_io_error(void) {
transfer_message_base(FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, -1, FALSE);
}
static void transfer_message_upload_cancelled(void) {
static void transfer_message_upload_error(bool_t cancel) {
if (transport_supported(LinphoneTransportTls)) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneChatRoom* chat_room;
......@@ -772,12 +778,14 @@ static void transfer_message_upload_cancelled(void) {
/*wait for file to be 25% uploaded and cancel the transfer */
BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer, 25, 60000));
linphone_chat_message_cancel_file_transfer(msg);
if (cancel) {
linphone_chat_message_cancel_file_transfer(msg);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered, 1));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered, 1));
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered, 1, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful, 0, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered, 1, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful, 0, int, "%d");
}
linphone_chat_message_unref(msg);
linphone_core_manager_destroy(pauline);
......@@ -785,6 +793,14 @@ static void transfer_message_upload_cancelled(void) {
}
}
static void transfer_message_upload_cancelled(void) {
transfer_message_upload_error(TRUE);
}
static void transfer_message_upload_aborted(void) {
transfer_message_upload_error(FALSE);
}
static void transfer_message_download_cancelled(void) {
LinphoneChatRoom* chat_room;
LinphoneChatMessage* msg;
......@@ -840,7 +856,6 @@ static void transfer_message_auto_download_aborted(void) {
/* wait for marie to receive pauline's msg */
BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageSent, 1, 5000));
linphone_chat_message_unref(msg);
BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceivedWithFile, 1, 1000));
linphone_core_manager_restart(marie, TRUE);
......@@ -885,6 +900,7 @@ static void transfer_message_auto_download_aborted(void) {
bc_free(send_filepath);
bc_free(receive_filepath);
}
linphone_chat_message_unref(msg);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
......@@ -3042,6 +3058,7 @@ test_t message_tests[] = {
TEST_NO_TAG("Transfer message with upload io error", transfer_message_with_upload_io_error),
TEST_NO_TAG("Transfer message with download io error", transfer_message_with_download_io_error),
TEST_NO_TAG("Transfer message upload cancelled", transfer_message_upload_cancelled),
TEST_NO_TAG("Transfer message upload aborted", transfer_message_upload_aborted),
TEST_NO_TAG("Transfer message download cancelled", transfer_message_download_cancelled),
TEST_NO_TAG("Transfer message auto download aborted", transfer_message_auto_download_aborted),
TEST_NO_TAG("Transfer 2 messages simultaneously", file_transfer_2_messages_simultaneously),
......