-
a39513ea
/*
* Copyright (c) 2010-2022 Belledonne Communications SARL.
*
* This file is part of Liblinphone
* (see https://gitlab.linphone.org/BC/public/liblinphone).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <map>
#include <string>
#include "bctoolbox/defs.h"
#include "c-wrapper/c-wrapper.h"
#include "address/address.h"
#include "call/call.h"
#include "conference.h"
#include "conference/conference-listener.h"
#include "conference/handlers/local-conference-event-handler.h"
#include "conference/handlers/remote-conference-event-handler.h"
#include "conference/local-conference.h"
#include "conference/participant.h"
#include "conference/remote-conference.h"
#include "liblinphone_tester.h"
#include "linphone/core.h"
#include "local_conference.h"
#include "private.h"
#include "shared_tester_functions.h"
#include "tester_utils.h"
#include "tools/private-access.h"
#include "linphone/api/c-conference-cbs.h"
#include "linphone/api/c-conference.h"
#include "xml/conference-info.h"
using namespace LinphonePrivate;
using namespace std;
static const char *first_notify =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
" <conference-info"
" xmlns=\"urn:ietf:params:xml:ns:conference-info\""
" entity=\"%s\""
" state=\"full\" version=\"1\">"
" <!--"
" CONFERENCE INFO"
" -->"
" <conference-description xmlns:p1=\"linphone:xml:ns:conference-info-linphone-extension\">"
" <subject>Agenda: This month's goals</subject>"
" <service-uris>"
" <entry>"
" <uri>http://sharepoint/salesgroup/</uri>"
" <purpose>web-page</purpose>"
" </entry>"
" </service-uris>"
" </conference-description>"
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
" <!--"
" CONFERENCE STATE"
" -->"
" <conference-state>"
" <user-count>33</user-count>"
" </conference-state>"
" <!--"
" USERS"
" -->"
" <users>"
" <user entity=\"sip:bob@example.com\" state=\"full\">"
" <display-text>Bob Hoskins</display-text>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:bob@pc33.example.com\">"
" <display-text>Bob's Laptop</display-text>"
" <status>disconnected</status>"
" <disconnection-method>departed</disconnection-method>"
" <disconnection-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <reason>bad voice quality</reason>"
" <by>sip:mike@example.com</by>"
" </disconnection-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>432424</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" </user>"
" <!--"
" USER"
" -->"
" <user entity=\"sip:alice@example.com\" state=\"full\">"
" <display-text>Alice</display-text>"
" <roles>"
" <entry>admin</entry>"
" <entry>participant</entry>"
" </roles>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:4kfk4j392jsu@example.com;grid=433kj4j3u\">"
" <status>connected</status>"
" <joining-method>dialed-out</joining-method>"
" <joining-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <by>sip:mike@example.com</by>"
" </joining-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>534232</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" <endpoint entity=\"sip:aliced48ed45@example.com;grid=54def54e8\">"
" <status>connected</status>"
" <joining-method>dialed-out</joining-method>"
" <joining-info>"
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
" <when>2005-03-04T20:00:00Z</when>"
" <by>sip:mike@example.com</by>"
" </joining-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>534232</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" </user>"
" </users>"
" </conference-info>";
static const char *sync_full_state_notify =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
" <conference-info"
" xmlns=\"urn:ietf:params:xml:ns:conference-info\""
" entity=\"%s\""
" state=\"full\" version=\"%0d\">"
" <!--"
" CONFERENCE INFO"
" -->"
" <conference-description xmlns:p1=\"linphone:xml:ns:conference-info-linphone-extension\">"
" <subject>Agenda: This month's goals</subject>"
" <service-uris>"
" <entry>"
" <uri>http://sharepoint/salesgroup/</uri>"
" <purpose>web-page</purpose>"
" </entry>"
" </service-uris>"
" </conference-description>"
" <!--"
" CONFERENCE STATE"
" -->"
" <conference-state>"
" <user-count>33</user-count>"
" </conference-state>"
" <!--"
" USERS"
" -->"
" <users>"
" <user entity=\"sip:bob@example.com\" state=\"full\">"
" <display-text>Bob Hoskins</display-text>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:bob@pc33.example.com\">"
" <display-text>Bob's Laptop</display-text>"
" <status>disconnected</status>"
" <disconnection-method>departed</disconnection-method>"
" <disconnection-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <reason>bad voice quality</reason>"
" <by>sip:mike@example.com</by>"
" </disconnection-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>432424</src-id>"
" <status>sendrecv</status>"
" </media>"
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
" </endpoint>"
" </user>"
" <!--"
" USER"
" -->"
" <user entity=\"sip:alice@example.com\" state=\"full\">"
" <display-text>Alice</display-text>"
" <roles>"
" <entry>admin</entry>"
" <entry>participant</entry>"
" </roles>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:4kfk4j392jsu@example.com;grid=433kj4j3u\">"
" <status>connected</status>"
" <joining-method>dialed-out</joining-method>"
" <joining-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <by>sip:mike@example.com</by>"
" </joining-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>534232</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" <endpoint entity=\"sip:aliced48ed45@example.com;grid=54def54e8\">"
" <status>connected</status>"
" <joining-method>dialed-out</joining-method>"
" <joining-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <by>sip:mike@example.com</by>"
" </joining-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>534232</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" </user>"
" <!--"
" USER"
" -->"
" <user entity=\"sip:frank@example.com\" state=\"full\">"
" <display-text>Bob Hoskins</display-text>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:frank@pc33.example.com\">"
" <display-text>Frank's Laptop</display-text>"
" <status>connected</status>"
" <joining-method>dialed-out</joining-method>"
" <joining-info>"
" <when>2005-03-04T20:06:00Z</when>"
" <by>sip:mike@example.com</by>"
" </joining-info>"
" <!--"
" MEDIA"
" -->"
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>432424</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" </user>"
" </users>"
" </conference-info>";
/*
static const char *first_notify_with_ephemeral = \
"<?xml version=\"1.0\" encoding=\"UTF-8\"?> "\
" <conference-info"\
" xmlns=\"urn:ietf:params:xml:ns:conference-info\""\
" entity=\"%s\""\
" state=\"full\" version=\"1\">"\
" <!--"\
" CONFERENCE INFO"\
" -->"\
" <conference-description xmlns:linphone-cie=\"linphone:xml:ns:conference-info-linphone-extension\">"\
" <subject>Agenda: This month's goals</subject>"\
" <service-uris>"\
" <entry>"\
" <uri>http://sharepoint/salesgroup/</uri>"\
" <purpose>web-page</purpose>"\
" </entry>"\
" </service-uris>"\
" <linphone-cie:ephemeral>"\
" <linphone-cie:mode>auto</linphone-cie:mode>"\
" </linphone-cie:ephemeral>"\
" </conference-description>"\
" <!--"\
" CONFERENCE STATE"\
" -->"\
" <conference-state>"\
" <user-count>33</user-count>"\
" </conference-state>"\
" <!--"\
" USERS"\
" -->"\
" <users>"\
" <user entity=\"sip:bob@example.com\" state=\"full\">"\
" <display-text>Bob Hoskins</display-text>"\
" <!--"\
" ENDPOINTS"\
" -->"\
" <endpoint entity=\"sip:bob@pc33.example.com\">"\
" <display-text>Bob's Laptop</display-text>"\
" <status>disconnected</status>"\
" <disconnection-method>departed</disconnection-method>"\
" <disconnection-info>"\
" <when>2005-03-04T20:00:00Z</when>"\
" <reason>bad voice quality</reason>"\
" <by>sip:mike@example.com</by>"\
" </disconnection-info>"\
" <!--"\
" MEDIA"\
" -->"\
" <media id=\"1\">"\
" <display-text>main audio</display-text>"\
" <type>audio</type>"\
" <label>34567</label>"\
" <src-id>432424</src-id>"\
" <status>sendrecv</status>"\
" </media>"\
" </endpoint>"\
" </user>"\
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
" <!--"\
" USER"\
" -->"\
" <user entity=\"sip:alice@example.com\" state=\"full\">"\
" <display-text>Alice</display-text>"\
" <roles>"\
" <entry>admin</entry>"\
" <entry>participant</entry>"\
" </roles>"\
" <!--"\
" ENDPOINTS"\
" -->"\
" <endpoint entity=\"sip:4kfk4j392jsu@example.com;grid=433kj4j3u\"
xmlns:linphone-cie=\"urn:oma:xml:prs:pidf:oma-pres\">"\
" <status>connected</status>"\
" <joining-method>dialed-out</joining-method>"\
" <joining-info>"\
" <when>2005-03-04T20:00:00Z</when>"\
" <by>sip:mike@example.com</by>"\
" </joining-info>"\
" <linphone-cie:service-description>"\
" <linphone-cie:service-id>ephemeral</linphone-cie:service-id>"\
" <linphone-cie:version>1.0</linphone-cie:version>"\
" </linphone-cie:service-description>"\
" <linphone-cie:service-description>"\
" <linphone-cie:service-id>groupchat</linphone-cie:service-id>"\
" <linphone-cie:version>1.1</linphone-cie:version>"\
" </linphone-cie:service-description>"\
" <linphone-cie:service-description>"\
" <linphone-cie:service-id>lime</linphone-cie:service-id>"\
" <linphone-cie:version>1.0</linphone-cie:version>"\
" </linphone-cie:service-description>"\
" <!--"\
" MEDIA"\
" -->"\
" <media id=\"1\">"\
" <display-text>main audio</display-text>"\
" <type>audio</type>"\
" <label>34567</label>"\
" <src-id>534232</src-id>"\
" <status>sendrecv</status>"\
" </media>"\
" </endpoint>"\
" <endpoint entity=\"sip:aliced48ed45@example.com;grid=54def54e8\">"\
" <status>connected</status>"\
" <joining-method>dialed-out</joining-method>"\
" <joining-info>"\
" <when>2005-03-04T20:00:00Z</when>"\
" <by>sip:mike@example.com</by>"\
" </joining-info>"\
" <!--"\
" MEDIA"\
" -->"\
" <media id=\"1\">"\
" <display-text>main audio</display-text>"\
" <type>audio</type>"\
" <label>34567</label>"\
" <src-id>534232</src-id>"\
" <status>sendrecv</status>"\
" </media>"\
" </endpoint>"\
" </user>"\
" </users>"\
" </conference-info>";
*/
static const char *participant_added_notify = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
" <conference-info"
" xmlns=\"urn:ietf:params:xml:ns:conference-info\""
" entity=\"%s\""
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
" state=\"partial\" version=\"2\">"
" <!--"
" CONFERENCE INFO"
" -->"
" <conference-description>"
" <subject>Agenda: This month's goals</subject>"
" <service-uris>"
" <entry>"
" <uri>http://sharepoint/salesgroup/</uri>"
" <purpose>web-page</purpose>"
" </entry>"
" </service-uris>"
" </conference-description>"
" <!--"
" CONFERENCE STATE"
" -->"
" <conference-state>"
" <user-count>33</user-count>"
" </conference-state>"
" <!--"
" USERS"
" -->"
" <users>"
" <user entity=\"sip:frank@example.com\" state=\"full\">"
" <display-text>Bob Hoskins</display-text>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:frank@pc33.example.com\">"
" <display-text>Frank's Laptop</display-text>"
" <status>disconnected</status>"
" <disconnection-method>departed</disconnection-method>"
" <disconnection-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <reason>bad voice quality</reason>"
" <by>sip:mike@example.com</by>"
" </disconnection-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>432424</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" </user>"
" </users>"
" </conference-info>";
static const char *participant_not_added_notify = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
" <conference-info"
" xmlns=\"urn:ietf:params:xml:ns:conference-info\""
" entity=\"%s\""
" state=\"partial\" version=\"2\">"
" <!--"
" CONFERENCE INFO"
" -->"
" <conference-description>"
" <subject>Agenda: This month's goals</subject>"
" <service-uris>"
" <entry>"
" <uri>http://sharepoint/salesgroup/</uri>"
" <purpose>web-page</purpose>"
" </entry>"
" </service-uris>"
" </conference-description>"
" <!--"
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
" CONFERENCE STATE"
" -->"
" <conference-state>"
" <user-count>33</user-count>"
" </conference-state>"
" <!--"
" USERS"
" -->"
" <users>"
" <user entity=\"sip:frank@example.com\" state=\"partial\">"
" <display-text>Bob Hoskins</display-text>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:frank@pc33.example.com\">"
" <display-text>Frank's Laptop</display-text>"
" <status>disconnected</status>"
" <disconnection-method>departed</disconnection-method>"
" <disconnection-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <reason>bad voice quality</reason>"
" <by>sip:mike@example.com</by>"
" </disconnection-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>432424</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" </user>"
" </users>"
" </conference-info>";
static const char *participant_device_not_added_notify =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
" <conference-info"
" xmlns=\"urn:ietf:params:xml:ns:conference-info\""
" entity=\"%s\""
" state=\"partial\" version=\"%0d\">"
" <!--"
" USERS"
" -->"
" <users state=\"full\">"
" <user entity=\"sip:frank@example.com\" state=\"partial\">"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:frank@pc34.example.com\" state=\"partial\">"
" <display-text>Frank's Laptop</display-text>"
" <status>connected</status>"
" <joining-method>dialed-out</joining-method>"
" <joining-info>"
" <when>2005-03-04T20:01:00Z</when>"
" <by>sip:mike@example.com</by>"
" </joining-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34517</label>"
" <src-id>432494</src-id>"
" <status>sendonly</status>"
" </media>"
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
" </endpoint>"
" </user>"
" </users>"
" </conference-info>";
static const char *participant_deleted_notify = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
" <conference-info"
" xmlns=\"urn:ietf:params:xml:ns:conference-info\""
" entity=\"%s\""
" state=\"partial\" version=\"2\">"
" <!--"
" CONFERENCE INFO"
" -->"
" <conference-description>"
" <subject>Agenda: This month's goals</subject>"
" <service-uris>"
" <entry>"
" <uri>http://sharepoint/salesgroup/</uri>"
" <purpose>web-page</purpose>"
" </entry>"
" </service-uris>"
" </conference-description>"
" <!--"
" CONFERENCE STATE"
" -->"
" <conference-state>"
" <user-count>33</user-count>"
" </conference-state>"
" <!--"
" USERS"
" -->"
" <users>"
" <user entity=\"sip:bob@example.com\" state=\"deleted\">"
" <display-text>Bob Hoskins</display-text>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:bob@pc33.example.com\">"
" <display-text>Bob's Laptop</display-text>"
" <status>disconnected</status>"
" <disconnection-method>departed</disconnection-method>"
" <disconnection-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <reason>bad voice quality</reason>"
" <by>sip:mike@example.com</by>"
" </disconnection-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>432424</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" </user>"
" </users>"
" </conference-info>";
static const char *participant_admined_notify = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
" <conference-info"
" xmlns=\"urn:ietf:params:xml:ns:conference-info\""
" entity=\"%s\""
" state=\"partial\" version=\"2\">"
" <!--"
" CONFERENCE INFO"
" -->"
" <conference-description>"
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
" <subject>Agenda: This month's goals</subject>"
" <service-uris>"
" <entry>"
" <uri>http://sharepoint/salesgroup/</uri>"
" <purpose>web-page</purpose>"
" </entry>"
" </service-uris>"
" </conference-description>"
" <!--"
" CONFERENCE STATE"
" -->"
" <conference-state>"
" <user-count>33</user-count>"
" </conference-state>"
" <!--"
" USERS"
" -->"
" <users>"
" <user entity=\"sip:bob@example.com\" state=\"partial\">"
" <display-text>Bob Hoskins</display-text>"
" <roles>"
" <entry>participant</entry>"
" <entry>admin</entry>"
" </roles>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:bob@pc33.example.com\">"
" <display-text>Bob's Laptop</display-text>"
" <status>disconnected</status>"
" <disconnection-method>departed</disconnection-method>"
" <disconnection-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <reason>bad voice quality</reason>"
" <by>sip:mike@example.com</by>"
" </disconnection-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>432424</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" </user>"
" </users>"
" </conference-info>";
static const char *participant_unadmined_notify = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
" <conference-info"
" xmlns=\"urn:ietf:params:xml:ns:conference-info\""
" entity=\"%s\""
" state=\"partial\" version=\"2\">"
" <!--"
" CONFERENCE INFO"
" -->"
" <conference-description>"
" <subject>Agenda: This month's goals</subject>"
" <service-uris>"
" <entry>"
" <uri>http://sharepoint/salesgroup/</uri>"
" <purpose>web-page</purpose>"
" </entry>"
" </service-uris>"
" </conference-description>"
" <!--"
" CONFERENCE STATE"
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
" -->"
" <conference-state>"
" <user-count>33</user-count>"
" </conference-state>"
" <!--"
" USERS"
" -->"
" <users>"
" <user entity=\"sip:alice@example.com\" state=\"partial\">"
" <display-text>Alice Hoskins</display-text>"
" <roles>"
" <entry>participant</entry>"
" </roles>"
" <!--"
" ENDPOINTS"
" -->"
" <endpoint entity=\"sip:alice@pc33.example.com\">"
" <display-text>Alice's Laptop</display-text>"
" <status>disconnected</status>"
" <disconnection-method>departed</disconnection-method>"
" <disconnection-info>"
" <when>2005-03-04T20:00:00Z</when>"
" <reason>bad voice quality</reason>"
" <by>sip:mike@example.com</by>"
" </disconnection-info>"
" <!--"
" MEDIA"
" -->"
" <media id=\"1\">"
" <display-text>main audio</display-text>"
" <type>audio</type>"
" <label>34567</label>"
" <src-id>432424</src-id>"
" <status>sendrecv</status>"
" </media>"
" </endpoint>"
" </user>"
" </users>"
" </conference-info>";
static const char *bobUri = "sip:bob@example.com";
static const char *aliceUri = "sip:alice@example.com";
static const char *frankUri = "sip:frank@example.com";
static const char *confUri = "sips:conf233@example.com";
L_ENABLE_ATTR_ACCESS(LocalConference, shared_ptr<LocalConferenceEventHandler>, eventHandler);
class ConferenceEventTester : public RemoteConference {
public:
ConferenceEventTester(const shared_ptr<Core> &core, const std::shared_ptr<Address> &confAddr);
~ConferenceEventTester();
private:
void onConferenceCreated(const std::shared_ptr<Address> &addr) override;
void onConferenceKeywordsChanged(const vector<string> &keywords) override;
void onConferenceTerminated(const std::shared_ptr<Address> &addr) override;
void onFirstNotifyReceived(const std::shared_ptr<Address> &addr) override;
void onParticipantAdded(const shared_ptr<ConferenceParticipantEvent> &event,
const std::shared_ptr<Participant> &participant) override;
void onParticipantRemoved(const shared_ptr<ConferenceParticipantEvent> &event,
const std::shared_ptr<Participant> &participant) override;
void onParticipantSetAdmin(const shared_ptr<ConferenceParticipantEvent> &event,
const std::shared_ptr<Participant> &participant) override;
void onSubjectChanged(const shared_ptr<ConferenceSubjectEvent> &event) override;
void onParticipantDeviceAdded(const shared_ptr<ConferenceParticipantDeviceEvent> &event,
const std::shared_ptr<ParticipantDevice> &device) override;
void onParticipantDeviceRemoved(const shared_ptr<ConferenceParticipantDeviceEvent> &event,
const std::shared_ptr<ParticipantDevice> &device) override;
public:
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
RemoteConferenceEventHandler *handler;
// address - admin
map<string, bool> participants;
map<string, int> participantDevices;
string confSubject;
bool oneToOne = false;
};
ConferenceEventTester::ConferenceEventTester(const shared_ptr<Core> &core, const std::shared_ptr<Address> &confAddr)
: RemoteConference(core, confAddr, nullptr, ConferenceParams::create(core->getCCore())) {
handler = new RemoteConferenceEventHandler(this, this);
}
ConferenceEventTester::~ConferenceEventTester() {
delete handler;
}
void ConferenceEventTester::onConferenceCreated(BCTBX_UNUSED(const std::shared_ptr<Address> &address)) {
}
void ConferenceEventTester::onConferenceKeywordsChanged(const vector<string> &keywords) {
for (const auto &k : keywords) {
if (k == "one-to-one") oneToOne = true;
}
}
void ConferenceEventTester::onConferenceTerminated(BCTBX_UNUSED(const std::shared_ptr<Address> &addr)) {
}
void ConferenceEventTester::onFirstNotifyReceived(BCTBX_UNUSED(const std::shared_ptr<Address> &addr)) {
}
void ConferenceEventTester::onParticipantAdded(const shared_ptr<ConferenceParticipantEvent> &event,
BCTBX_UNUSED(const std::shared_ptr<Participant> &participant)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
participants.insert({addr->toString(), false});
participantDevices.insert({addr->toString(), 0});
}
void ConferenceEventTester::onParticipantRemoved(const shared_ptr<ConferenceParticipantEvent> &event,
BCTBX_UNUSED(const std::shared_ptr<Participant> &participant)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
participants.erase(addr->toString());
participantDevices.erase(addr->toString());
}
void ConferenceEventTester::onParticipantSetAdmin(const shared_ptr<ConferenceParticipantEvent> &event,
BCTBX_UNUSED(const std::shared_ptr<Participant> &participant)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
auto it = participants.find(addr->toString());
if (it != participants.end()) it->second = (event->getType() == EventLog::Type::ConferenceParticipantSetAdmin);
}
void ConferenceEventTester::onSubjectChanged(const shared_ptr<ConferenceSubjectEvent> &event) {
confSubject = event->getSubject();
}
void ConferenceEventTester::onParticipantDeviceAdded(const shared_ptr<ConferenceParticipantDeviceEvent> &event,
BCTBX_UNUSED(const std::shared_ptr<ParticipantDevice> &device)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
auto it = participantDevices.find(addr->toString());
if (it != participantDevices.end()) it->second++;
}
void ConferenceEventTester::onParticipantDeviceRemoved(const shared_ptr<ConferenceParticipantDeviceEvent> &event,
BCTBX_UNUSED(const std::shared_ptr<ParticipantDevice> &device)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
auto it = participantDevices.find(addr->toString());
if (it != participantDevices.end() && it->second > 0) it->second--;
}
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
class LocalConferenceTester : public LocalConference {
public:
LocalConferenceTester(const std::shared_ptr<Core> &core,
const std::shared_ptr<Address> &myAddress,
CallSessionListener *listener)
: LocalConference(core, myAddress, listener, ConferenceParams::create(core->getCCore())) {
}
virtual ~LocalConferenceTester() {
}
/* ConferenceInterface */
// Addressing compilation error -Werror=overloaded-virtual
using LinphonePrivate::Conference::addParticipant;
bool addParticipant(const std::shared_ptr<Address> &addr) override {
bool status = LocalConference::addParticipant(addr);
std::shared_ptr<Participant> p = findParticipant(addr);
p->addDevice(addr);
if (status) {
notifyParticipantAdded(time(nullptr), false, p);
}
return status;
}
bool removeParticipant(const std::shared_ptr<Participant> &participant) override {
participant->clearDevices();
bool status = LocalConference::removeParticipant(participant);
if (status) {
notifyParticipantRemoved(time(nullptr), false, participant);
}
return status;
}
void setSubject(const std::string &subject) override {
LocalConference::setSubject(subject);
notifySubjectChanged(time(nullptr), false, subject);
}
};
class ConferenceListenerInterfaceTester : public ConferenceListenerInterface {
public:
ConferenceListenerInterfaceTester() = default;
~ConferenceListenerInterfaceTester() = default;
private:
void onParticipantAdded(const shared_ptr<ConferenceParticipantEvent> &event,
const std::shared_ptr<Participant> &participant) override;
void onParticipantRemoved(const shared_ptr<ConferenceParticipantEvent> &event,
const std::shared_ptr<Participant> &participant) override;
void onParticipantSetAdmin(const shared_ptr<ConferenceParticipantEvent> &event,
const std::shared_ptr<Participant> &participant) override;
void onSubjectChanged(const shared_ptr<ConferenceSubjectEvent> &event) override;
void onParticipantDeviceAdded(const shared_ptr<ConferenceParticipantDeviceEvent> &event,
const std::shared_ptr<ParticipantDevice> &device) override;
void onParticipantDeviceRemoved(const shared_ptr<ConferenceParticipantDeviceEvent> &event,
const std::shared_ptr<ParticipantDevice> &device) override;
public:
// first = address
// second = isAdmin
map<string, bool> participants;
// first = address
// second = number of devices
map<string, int> participantDevices;
string confSubject;
unsigned int lastNotify = 1;
};
void ConferenceListenerInterfaceTester::onParticipantAdded(
const shared_ptr<ConferenceParticipantEvent> &event,
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
BCTBX_UNUSED(const std::shared_ptr<Participant> &participant)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
participants.insert({addr->toString(), false});
participantDevices.insert({addr->toString(), 0});
lastNotify++;
}
void ConferenceListenerInterfaceTester::onParticipantRemoved(
const shared_ptr<ConferenceParticipantEvent> &event,
BCTBX_UNUSED(const std::shared_ptr<Participant> &participant)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
participants.erase(addr->toString());
participantDevices.erase(addr->toString());
lastNotify++;
}
void ConferenceListenerInterfaceTester::onParticipantSetAdmin(
const shared_ptr<ConferenceParticipantEvent> &event,
BCTBX_UNUSED(const std::shared_ptr<Participant> &participant)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
auto it = participants.find(addr->toString());
if (it != participants.end()) it->second = (event->getType() == EventLog::Type::ConferenceParticipantSetAdmin);
lastNotify++;
}
void ConferenceListenerInterfaceTester::onSubjectChanged(const shared_ptr<ConferenceSubjectEvent> &event) {
confSubject = event->getSubject();
lastNotify++;
}
void ConferenceListenerInterfaceTester::onParticipantDeviceAdded(
const shared_ptr<ConferenceParticipantDeviceEvent> &event,
BCTBX_UNUSED(const std::shared_ptr<ParticipantDevice> &device)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
auto it = participantDevices.find(addr->toString());
if (it != participantDevices.end()) it->second++;
lastNotify++;
}
void ConferenceListenerInterfaceTester::onParticipantDeviceRemoved(
const shared_ptr<ConferenceParticipantDeviceEvent> &event,
BCTBX_UNUSED(const std::shared_ptr<ParticipantDevice> &device)) {
const std::shared_ptr<Address> addr = event->getParticipantAddress();
auto it = participantDevices.find(addr->toString());
if (it != participantDevices.end() && it->second > 0) it->second--;
lastNotify++;
}
static void
setParticipantAsAdmin(shared_ptr<LocalConferenceTester> localConf, std::shared_ptr<Address> addr, bool isAdmin) {
shared_ptr<Participant> p = localConf->findParticipant(addr);
p->setAdmin(isAdmin);
localConf->notifyParticipantSetAdmin(time(nullptr), false, p, isAdmin);
}
void first_notify_parsing() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri);
std::shared_ptr<Address> addr = Address::toCpp(confAddress)->getSharedFromThis();
linphone_address_unref(confAddress);
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri);
LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
size_t size = strlen(first_notify) + strlen(confUri);
char *notify = new char[size];
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
snprintf(notify, size, first_notify, confUri);
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
Content content;
content.setBodyFromUtf8(notify);
content.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content);
delete[] notify;
BC_ASSERT_STRING_EQUAL(tester->confSubject.c_str(), "Agenda: This month's goals");
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
char *bobAddrStr = linphone_address_as_string(bobAddr);
char *aliceAddrStr = linphone_address_as_string(aliceAddr);
BC_ASSERT_TRUE(tester->participants.find(bobAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(bobAddrStr)->second);
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr)->second);
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(tester->participantDevices.find(bobAddrStr) != tester->participantDevices.end());
BC_ASSERT_TRUE(tester->participantDevices.find(aliceAddrStr) != tester->participantDevices.end());
BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddrStr)->second, 1, int, "%d");
BC_ASSERT_EQUAL(tester->participantDevices.find(aliceAddrStr)->second, 2, int, "%d");
bctbx_free(bobAddrStr);
bctbx_free(aliceAddrStr);
linphone_address_unref(bobAddr);
linphone_address_unref(aliceAddr);
tester = nullptr;
linphone_core_manager_destroy(marie);
}
void first_notify_with_extensions_parsing() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri);
std::shared_ptr<Address> addr = Address::toCpp(confAddress)->getSharedFromThis();
linphone_address_unref(confAddress);
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri);
LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
size_t size = strlen(first_notify) + strlen(confUri);
char *notify = new char[size];
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
snprintf(notify, size, first_notify, confUri);
Content content;
content.setBodyFromUtf8(notify);
content.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content);
delete[] notify;
BC_ASSERT_STRING_EQUAL(tester->confSubject.c_str(), "Agenda: This month's goals");
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
char *bobAddrStr = linphone_address_as_string(bobAddr);
char *aliceAddrStr = linphone_address_as_string(aliceAddr);
BC_ASSERT_TRUE(tester->participants.find(bobAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(bobAddrStr)->second);
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr)->second);
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(tester->participantDevices.find(bobAddrStr) != tester->participantDevices.end());
BC_ASSERT_TRUE(tester->participantDevices.find(aliceAddrStr) != tester->participantDevices.end());
BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddrStr)->second, 1, int, "%d");
BC_ASSERT_EQUAL(tester->participantDevices.find(aliceAddrStr)->second, 2, int, "%d");
bctbx_free(bobAddrStr);
bctbx_free(aliceAddrStr);
linphone_address_unref(bobAddr);
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
linphone_address_unref(aliceAddr);
tester = nullptr;
linphone_core_manager_destroy(marie);
}
void first_notify_parsing_wrong_conf() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, "sips:conf322@example.com");
std::shared_ptr<Address> addr = Address::toCpp(confAddress)->getSharedFromThis();
linphone_address_unref(confAddress);
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri);
LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
size_t size = strlen(first_notify) + strlen(confUri);
char *notify = new char[size];
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
snprintf(notify, size, first_notify, confUri);
Content content;
content.setBodyFromUtf8(notify);
content.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content);
delete[] notify;
BC_ASSERT_EQUAL((int)tester->participants.size(), 0, int, "%d");
char *bobAddrStr = linphone_address_as_string(bobAddr);
char *aliceAddrStr = linphone_address_as_string(aliceAddr);
BC_ASSERT_FALSE(tester->participants.find(bobAddrStr) != tester->participants.end());
BC_ASSERT_FALSE(tester->participants.find(aliceAddrStr) != tester->participants.end());
bctbx_free(bobAddrStr);
bctbx_free(aliceAddrStr);
linphone_address_unref(bobAddr);
linphone_address_unref(aliceAddr);
tester = nullptr;
linphone_core_manager_destroy(marie);
}
void participant_added_parsing() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri);
std::shared_ptr<Address> addr = Address::toCpp(confAddress)->getSharedFromThis();
linphone_address_unref(confAddress);
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri);
LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
LinphoneAddress *frankAddr = linphone_core_interpret_url(marie->lc, frankUri);
size_t size = strlen(first_notify) + strlen(confUri);
char *notify = new char[size];
size_t size2 = strlen(participant_added_notify) + strlen(confUri);
char *notify_added = new char[size2];
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
snprintf(notify, size, first_notify, confUri);
Content content;
content.setBodyFromUtf8(notify);
content.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content);
delete[] notify;
char *bobAddrStr = linphone_address_as_string(bobAddr);
char *aliceAddrStr = linphone_address_as_string(aliceAddr);
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(bobAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(bobAddrStr)->second);
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr)->second);
bctbx_free(bobAddrStr);
bctbx_free(aliceAddrStr);
snprintf(notify_added, size2, participant_added_notify, confUri);
Content content_added;
content_added.setBodyFromUtf8(notify_added);
content_added.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content_added);
delete[] notify_added;
char *frankAddrStr = linphone_address_as_string(frankAddr);
BC_ASSERT_EQUAL((int)tester->participants.size(), 3, int, "%d");
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 3, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(frankAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(frankAddrStr)->second);
bctbx_free(frankAddrStr);
linphone_address_unref(bobAddr);
linphone_address_unref(aliceAddr);
linphone_address_unref(frankAddr);
tester = nullptr;
linphone_core_manager_destroy(marie);
}
void participant_not_added_parsing() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
setup_mgr_for_conference(marie, NULL);
LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri);
std::shared_ptr<Address> addr = Address::toCpp(confAddress)->getSharedFromThis();
linphone_address_unref(confAddress);
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri);
LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
LinphoneAddress *frankAddr = linphone_core_interpret_url(marie->lc, frankUri);
size_t size = strlen(first_notify) + strlen(confUri);
char *notify = new char[size];
size_t size2 = strlen(participant_not_added_notify) + strlen(confUri);
char *notify_not_added = new char[size2];
size_t size3 = strlen(sync_full_state_notify) + strlen(confUri) + sizeof(int);
char *notify_full_state_sync = new char[size3];
size_t size4 = strlen(participant_device_not_added_notify) + strlen(confUri) + sizeof(int);
char *notify_device_not_added = new char[size4];
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
const_cast<ConferenceId &>(tester->handler->getConferenceId())
.setLocalAddress(Address::create(linphone_core_get_identity(marie->lc)));
snprintf(notify, size, first_notify, confUri);
Content content;
content.setBodyFromUtf8(notify);
content.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content);
delete[] notify;
char *bobAddrStr = linphone_address_as_string(bobAddr);
char *aliceAddrStr = linphone_address_as_string(aliceAddr);
char *frankAddrStr = linphone_address_as_string(frankAddr);
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 2, int, "%d");
1191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
BC_ASSERT_TRUE(tester->participants.find(bobAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(bobAddrStr)->second);
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr)->second);
bctbx_free(bobAddrStr);
bctbx_free(aliceAddrStr);
stats initial_marie_stats = marie->stat;
snprintf(notify_not_added, size2, participant_not_added_notify, confUri);
Content content_not_added;
content_not_added.setBodyFromUtf8(notify_not_added);
content_not_added.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content_not_added);
delete[] notify_not_added;
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
BC_ASSERT_FALSE(tester->participants.find(frankAddrStr) != tester->participants.end());
// Add a short wait to ensure that all NOTIFYs are replied
BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneSubscriptionOutgoingProgress,
(initial_marie_stats.number_of_LinphoneSubscriptionOutgoingProgress + 1), 5000));
snprintf(notify_full_state_sync, size3, sync_full_state_notify, confUri, tester->handler->getLastNotify() + 1);
Content content_full_state_updated;
content_full_state_updated.setBodyFromUtf8(notify_full_state_sync);
content_full_state_updated.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content_full_state_updated);
delete[] notify_full_state_sync;
BC_ASSERT_EQUAL((int)tester->participants.size(), 3, int, "%d");
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 3, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(frankAddrStr) != tester->participants.end());
snprintf(notify_device_not_added, size4, participant_device_not_added_notify, confUri,
tester->handler->getLastNotify() + 1);
initial_marie_stats = marie->stat;
Content content_device_not_added;
content_device_not_added.setBodyFromUtf8(notify_device_not_added);
content_device_not_added.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content_device_not_added);
delete[] notify_device_not_added;
BC_ASSERT_EQUAL((int)tester->participants.size(), 3, int, "%d");
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 3, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(frankAddrStr) != tester->participants.end());
bctbx_free(frankAddrStr);
// Add a short wait to ensure that all NOTIFYs are replied
BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneSubscriptionOutgoingProgress,
(initial_marie_stats.number_of_LinphoneSubscriptionOutgoingProgress + 1), 5000));
linphone_address_unref(bobAddr);
linphone_address_unref(aliceAddr);
linphone_address_unref(frankAddr);
tester = nullptr;
destroy_mgr_in_conference(marie);
}
void participant_deleted_parsing() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri);
std::shared_ptr<Address> addr = Address::toCpp(confAddress)->getSharedFromThis();
linphone_address_unref(confAddress);
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
1261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri);
LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
size_t size = strlen(first_notify) + strlen(confUri);
char *notify = new char[size];
size_t size2 = strlen(participant_deleted_notify) + strlen(confUri);
char *notify_deleted = new char[size2];
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
snprintf(notify, size, first_notify, confUri);
Content content;
content.setBodyFromUtf8(notify);
content.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content);
delete[] notify;
char *bobAddrStr = linphone_address_as_string(bobAddr);
char *aliceAddrStr = linphone_address_as_string(aliceAddr);
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(bobAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(bobAddrStr)->second);
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr)->second);
snprintf(notify_deleted, size2, participant_deleted_notify, confUri);
Content content_deleted;
content_deleted.setBodyFromUtf8(notify_deleted);
content_deleted.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content_deleted);
delete[] notify_deleted;
BC_ASSERT_EQUAL((int)tester->participants.size(), 1, int, "%d");
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 1, int, "%d");
BC_ASSERT_FALSE(tester->participants.find(bobAddrStr) != tester->participants.end());
bctbx_free(bobAddrStr);
bctbx_free(aliceAddrStr);
linphone_address_unref(bobAddr);
linphone_address_unref(aliceAddr);
tester = nullptr;
linphone_core_manager_destroy(marie);
}
void participant_admined_parsing() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri);
std::shared_ptr<Address> addr = Address::toCpp(confAddress)->getSharedFromThis();
linphone_address_unref(confAddress);
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri);
LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
size_t size = strlen(first_notify) + strlen(confUri);
char *notify = new char[size];
size_t size2 = strlen(participant_admined_notify) + strlen(confUri);
char *notify_admined = new char[size2];
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
snprintf(notify, size, first_notify, confUri);
Content content;
content.setBodyFromUtf8(notify);
content.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content);
1331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
delete[] notify;
char *bobAddrStr = linphone_address_as_string(bobAddr);
char *aliceAddrStr = linphone_address_as_string(aliceAddr);
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(bobAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(bobAddrStr)->second);
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr)->second);
snprintf(notify_admined, size2, participant_admined_notify, confUri);
Content content_admined;
content_admined.setBodyFromUtf8(notify_admined);
content_admined.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content_admined);
delete[] notify_admined;
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(bobAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(tester->participants.find(bobAddrStr)->second);
bctbx_free(bobAddrStr);
bctbx_free(aliceAddrStr);
linphone_address_unref(bobAddr);
linphone_address_unref(aliceAddr);
tester = nullptr;
linphone_core_manager_destroy(marie);
}
void participant_unadmined_parsing() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri);
std::shared_ptr<Address> addr = Address::toCpp(confAddress)->getSharedFromThis();
linphone_address_unref(confAddress);
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri);
LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
size_t size = strlen(first_notify) + strlen(confUri);
char *notify = new char[size];
size_t size2 = strlen(participant_unadmined_notify) + strlen(confUri);
char *notify_unadmined = new char[size2];
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
snprintf(notify, size, first_notify, confUri);
Content content;
content.setBodyFromUtf8(notify);
content.setContentType(ContentType::ConferenceInfo);
tester->handler->notifyReceived(content);
delete[] notify;
char *bobAddrStr = linphone_address_as_string(bobAddr);
char *aliceAddrStr = linphone_address_as_string(aliceAddr);
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(bobAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(bobAddrStr)->second);
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr)->second);
snprintf(notify_unadmined, size2, participant_unadmined_notify, confUri);
Content content_unadmined;
content_unadmined.setBodyFromUtf8(notify_unadmined);
content_unadmined.setContentType(ContentType::ConferenceInfo);
1401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
tester->handler->notifyReceived(content_unadmined);
delete[] notify_unadmined;
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(aliceAddrStr) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(aliceAddrStr)->second);
bctbx_free(bobAddrStr);
bctbx_free(aliceAddrStr);
linphone_address_unref(bobAddr);
linphone_address_unref(aliceAddr);
tester = nullptr;
linphone_core_manager_destroy(marie);
}
void send_first_notify() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
shared_ptr<LocalConference> localConf =
make_shared<LocalConference>(pauline->lc->cppPtr, addr, nullptr, ConferenceParams::create(pauline->lc));
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri);
std::shared_ptr<Address> bobAddr = Address::toCpp(cBobAddr)->getSharedFromThis();
linphone_address_unref(cBobAddr);
LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
std::shared_ptr<Address> aliceAddr = Address::toCpp(cAliceAddr)->getSharedFromThis();
linphone_address_unref(cAliceAddr);
localConf->addParticipant(bobAddr);
localConf->addParticipant(aliceAddr);
localConf->setSubject("A random test subject");
shared_ptr<Participant> alice = localConf->findParticipant(aliceAddr);
alice->setAdmin(true);
LocalConferenceEventHandler *localHandler = (L_ATTR_GET(localConf.get(), eventHandler)).get();
localConf->setConferenceAddress(addr);
Content content = localHandler->createNotifyFullState(NULL);
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
tester->handler->notifyReceived(content);
BC_ASSERT_STRING_EQUAL(tester->confSubject.c_str(), "A random test subject");
BC_ASSERT_EQUAL((int)tester->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(tester->participants.find(bobAddr->toString()) != tester->participants.end());
BC_ASSERT_TRUE(tester->participants.find(aliceAddr->toString()) != tester->participants.end());
BC_ASSERT_TRUE(!tester->participants.find(bobAddr->toString())->second);
BC_ASSERT_TRUE(tester->participants.find(aliceAddr->toString())->second);
tester = nullptr;
localConf = nullptr;
alice = nullptr;
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
void send_added_notify_through_address() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
shared_ptr<LocalConferenceTester> localConf =
make_shared<LocalConferenceTester>(pauline->lc->cppPtr, addr, nullptr);
1471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri);
std::shared_ptr<Address> bobAddr = Address::toCpp(cBobAddr)->getSharedFromThis();
linphone_address_unref(cBobAddr);
LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
std::shared_ptr<Address> aliceAddr = Address::toCpp(cAliceAddr)->getSharedFromThis();
linphone_address_unref(cAliceAddr);
LinphoneAddress *cFrankAddr = linphone_core_interpret_url(marie->lc, frankUri);
std::shared_ptr<Address> frankAddr = Address::toCpp(cFrankAddr)->getSharedFromThis();
linphone_address_unref(cFrankAddr);
localConf->addParticipant(bobAddr);
localConf->addParticipant(aliceAddr);
setParticipantAsAdmin(localConf, aliceAddr, true);
localConf->setConferenceAddress(addr);
BC_ASSERT_EQUAL((int)confListener->participants.size(), 2, int, "%d");
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
// Admin check
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
unsigned int lastNotifyCount = confListener->lastNotify;
localConf->notifyParticipantAdded(time(nullptr), false, Participant::create(localConf.get(), frankAddr));
BC_ASSERT_EQUAL((int)confListener->participants.size(), 3, int, "%d");
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), 3, int, "%d");
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(frankAddr->toString()) != confListener->participants.end());
// Admin check
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
BC_ASSERT_TRUE(!confListener->participants.find(frankAddr->toString())->second);
BC_ASSERT_EQUAL(localConf->getLastNotify(), (lastNotifyCount + 1), int, "%d");
localConf = nullptr;
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void
remove_participant_from_conference_through_call(bctbx_list_t **removed_mgrs,
bctbx_list_t **participants_mgrs,
bctbx_list_t *lcs,
std::shared_ptr<ConferenceListenerInterfaceTester> confListener,
shared_ptr<MediaConference::LocalConference> conf,
LinphoneCoreManager *conf_mgr,
LinphoneCoreManager *participant_mgr) {
stats initial_conf_stats = conf_mgr->stat;
stats initial_participant_stats = participant_mgr->stat;
stats *other_participants_initial_stats = NULL;
bctbx_list_t *other_participants = NULL;
int counter = 1;
for (bctbx_list_t *it = *participants_mgrs; it; it = bctbx_list_next(it)) {
LinphoneCoreManager *m = reinterpret_cast<LinphoneCoreManager *>(bctbx_list_get_data(it));
if ((m != participant_mgr) && (m != conf_mgr)) {
// Allocate memory
other_participants_initial_stats =
(stats *)realloc(other_participants_initial_stats, counter * sizeof(stats));
// Append element
other_participants_initial_stats[counter - 1] = m->stat;
// Increment counter
1541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610
counter++;
other_participants = bctbx_list_append(other_participants, m);
}
}
LinphoneCall *confCall = linphone_core_get_call_by_remote_address2(conf_mgr->lc, participant_mgr->identity);
int participantSize = (int)confListener->participants.size();
conf->removeParticipant(Call::toCpp(confCall)->getSharedFromThis()->getActiveSession(), true);
// Remove participant from list of managers
*participants_mgrs = bctbx_list_remove(*participants_mgrs, participant_mgr);
*removed_mgrs = bctbx_list_append(*removed_mgrs, participant_mgr);
// Calls are paused when removing a participant
BC_ASSERT_TRUE(wait_for_list(lcs, &conf_mgr->stat.number_of_LinphoneCallPausing,
(initial_conf_stats.number_of_LinphoneCallPausing + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &conf_mgr->stat.number_of_LinphoneCallPaused,
(initial_conf_stats.number_of_LinphoneCallPaused + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneCallPausedByRemote,
(initial_participant_stats.number_of_LinphoneCallPausedByRemote + 1), 5000));
// Wait for conferences to be terminated
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneConferenceStateTerminationPending,
(initial_participant_stats.number_of_LinphoneConferenceStateTerminationPending + 1),
5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneConferenceStateTerminated,
(initial_participant_stats.number_of_LinphoneConferenceStateTerminated + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneConferenceStateDeleted,
(initial_participant_stats.number_of_LinphoneConferenceStateDeleted + 1), 5000));
int expectedParticipants = 0;
if (participantSize == 2) {
expectedParticipants = 0;
} else {
expectedParticipants = (participantSize - 1);
}
LinphoneCall *participantCall = linphone_core_get_current_call(participant_mgr->lc);
BC_ASSERT_PTR_NOT_NULL(participantCall);
if (participantCall) {
const LinphoneAddress *cParticipantAddress = linphone_call_get_to_address(participantCall);
std::string participantUri =
Address::toCpp(const_cast<LinphoneAddress *>(cParticipantAddress))->asStringUriOnly();
BC_ASSERT_TRUE(confListener->participants.find(participantUri) == confListener->participants.end());
}
// Other participants call should not have their state modified
if (other_participants != NULL) {
int idx = 0;
for (bctbx_list_t *itm = other_participants; itm; itm = bctbx_list_next(itm)) {
LinphoneCoreManager *m = reinterpret_cast<LinphoneCoreManager *>(bctbx_list_get_data(itm));
// If removing last participant, then its call is kicked out of conference
// - Remote conference is deleted
// - parameters are updated
if (participantSize == 2) {
BC_ASSERT_TRUE(wait_for_list(
lcs, &m->stat.number_of_LinphoneCallUpdatedByRemote,
(other_participants_initial_stats[idx].number_of_LinphoneCallUpdatedByRemote + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(
lcs, &m->stat.number_of_LinphoneCallStreamsRunning,
(other_participants_initial_stats[idx].number_of_LinphoneCallStreamsRunning + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(
lcs, &participant_mgr->stat.number_of_LinphoneConferenceStateTerminationPending,
(initial_participant_stats.number_of_LinphoneConferenceStateTerminationPending + 1), 5000));
BC_ASSERT_TRUE(
wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneConferenceStateTerminated,
(initial_participant_stats.number_of_LinphoneConferenceStateTerminated + 1), 5000));
1611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneConferenceStateDeleted,
(initial_participant_stats.number_of_LinphoneConferenceStateDeleted + 1),
5000));
*participants_mgrs = bctbx_list_remove(*participants_mgrs, m);
*removed_mgrs = bctbx_list_append(*removed_mgrs, m);
} else {
BC_ASSERT_EQUAL(m->stat.number_of_LinphoneCallStreamsRunning,
other_participants_initial_stats[idx].number_of_LinphoneCallStreamsRunning, int, "%0d");
}
BC_ASSERT_EQUAL(m->stat.number_of_LinphoneCallEnd,
other_participants_initial_stats[idx].number_of_LinphoneCallEnd, int, "%0d");
BC_ASSERT_EQUAL(m->stat.number_of_LinphoneCallReleased,
other_participants_initial_stats[idx].number_of_LinphoneCallReleased, int, "%0d");
idx++;
}
}
BC_ASSERT_EQUAL((int)confListener->participants.size(), expectedParticipants, int, "%d");
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), expectedParticipants, int, "%d");
if (other_participants_initial_stats) {
ms_free(other_participants_initial_stats);
}
if (other_participants) {
bctbx_list_free(other_participants);
}
}
static void remove_head_participant_list_from_conference_through_call(
bctbx_list_t **removed_mgrs,
bctbx_list_t **participants_mgrs,
bctbx_list_t *lcs,
std::shared_ptr<ConferenceListenerInterfaceTester> confListener,
shared_ptr<MediaConference::LocalConference> conf,
LinphoneCoreManager *conf_mgr) {
LinphoneCoreManager *del_mgr = nullptr;
for (bctbx_list_t *it = *participants_mgrs; it; it = bctbx_list_next(it)) {
del_mgr = reinterpret_cast<LinphoneCoreManager *>(bctbx_list_get_data(it));
if (del_mgr != conf_mgr) {
remove_participant_from_conference_through_call(removed_mgrs, participants_mgrs, lcs, confListener, conf,
conf_mgr, del_mgr);
break;
}
}
}
static LinphoneCall *
add_participant_to_conference_through_call(bctbx_list_t **mgrs,
bctbx_list_t *lcs,
std::shared_ptr<ConferenceListenerInterfaceTester> &confListener,
shared_ptr<MediaConference::LocalConference> &conf,
LinphoneCoreManager *conf_mgr,
LinphoneCoreManager *participant_mgr,
bool_t pause_call) {
stats initial_conf_stats = conf_mgr->stat;
stats initial_participant_stats = participant_mgr->stat;
int init_subscription_count = conf_mgr->subscription_received;
stats *other_participants_initial_stats = NULL;
bctbx_list_t *other_participants = NULL;
int counter = 1;
for (bctbx_list_t *it = *mgrs; it; it = bctbx_list_next(it)) {
LinphoneCoreManager *m = reinterpret_cast<LinphoneCoreManager *>(bctbx_list_get_data(it));
if ((m != participant_mgr) && (m != conf_mgr)) {
// Allocate memory
other_participants_initial_stats =
1681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
(stats *)realloc(other_participants_initial_stats, counter * sizeof(stats));
// Append element
other_participants_initial_stats[counter - 1] = m->stat;
// Increment counter
counter++;
other_participants = bctbx_list_append(other_participants, m);
}
}
BC_ASSERT_TRUE(call(conf_mgr, participant_mgr));
LinphoneCall *participantCall = linphone_core_get_current_call(participant_mgr->lc);
BC_ASSERT_PTR_NOT_NULL(participantCall);
LinphoneCall *confCall = linphone_core_get_call_by_remote_address2(conf_mgr->lc, participant_mgr->identity);
BC_ASSERT_PTR_NOT_NULL(confCall);
if (pause_call) {
if (participantCall) {
BC_ASSERT_TRUE(linphone_call_get_state(participantCall) == LinphoneCallStreamsRunning);
}
if (confCall) {
BC_ASSERT_TRUE(linphone_call_get_state(confCall) == LinphoneCallStreamsRunning);
// Conference pauses the call
linphone_call_pause(confCall);
}
BC_ASSERT_TRUE(wait_for_list(lcs, &conf_mgr->stat.number_of_LinphoneCallPaused,
(initial_conf_stats.number_of_LinphoneCallPaused + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneCallPausedByRemote,
(initial_participant_stats.number_of_LinphoneCallPausedByRemote + 1), 5000));
} else {
if (confCall) {
BC_ASSERT_TRUE(linphone_call_get_state(confCall) != LinphoneCallPausing);
BC_ASSERT_TRUE(linphone_call_get_state(confCall) != LinphoneCallPaused);
}
if (participantCall) {
BC_ASSERT_TRUE(linphone_call_get_state(participantCall) != LinphoneCallPausedByRemote);
}
}
participantCall = linphone_core_get_current_call(participant_mgr->lc);
BC_ASSERT_PTR_NOT_NULL(participantCall);
int participantSize = (int)confListener->participants.size();
int participantDeviceSize = (int)confListener->participantDevices.size();
conf->addParticipant(Call::toCpp(confCall)->getSharedFromThis());
// Prepend participant managers to ensure that conference focus is last
*mgrs = bctbx_list_prepend(*mgrs, participant_mgr);
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneConferenceStateCreationPending,
initial_participant_stats.number_of_LinphoneConferenceStateCreationPending + 1, 5000));
// Stream due to call and stream due to the addition to the conference
BC_ASSERT_TRUE(wait_for_list(lcs, &conf_mgr->stat.number_of_LinphoneCallStreamsRunning,
(initial_conf_stats.number_of_LinphoneCallStreamsRunning + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(
lcs, &participant_mgr->stat.number_of_LinphoneCallStreamsRunning,
(initial_participant_stats.number_of_LinphoneCallStreamsRunning + 1 + (pause_call) ? 1 : 0), 5000));
if (pause_call) {
BC_ASSERT_TRUE(wait_for_list(lcs, &conf_mgr->stat.number_of_LinphoneCallResuming,
(initial_conf_stats.number_of_LinphoneCallResuming + 1), 5000));
} else {
BC_ASSERT_TRUE(wait_for_list(lcs, &conf_mgr->stat.number_of_LinphoneCallUpdating,
(initial_conf_stats.number_of_LinphoneCallUpdating + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneCallUpdatedByRemote,
(initial_participant_stats.number_of_LinphoneCallUpdatedByRemote + 1), 5000));
}
BC_ASSERT_TRUE(wait_for_list(lcs, &conf_mgr->stat.number_of_LinphoneCallStreamsRunning,
1751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820
(initial_conf_stats.number_of_LinphoneCallStreamsRunning + 2), 5000));
BC_ASSERT_TRUE(wait_for_list(
lcs, &participant_mgr->stat.number_of_LinphoneCallStreamsRunning,
(initial_participant_stats.number_of_LinphoneCallStreamsRunning + 2 + (pause_call) ? 1 : 0), 5000));
// Check subscriptions
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_LinphoneSubscriptionOutgoingProgress,
(initial_participant_stats.number_of_LinphoneSubscriptionOutgoingProgress + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &conf_mgr->stat.number_of_LinphoneSubscriptionIncomingReceived,
(initial_conf_stats.number_of_LinphoneSubscriptionIncomingReceived + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &conf_mgr->subscription_received, (init_subscription_count + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &participant_mgr->stat.number_of_NotifyFullStateReceived,
(initial_participant_stats.number_of_NotifyFullStateReceived + 1), 5000));
if (other_participants != NULL) {
int idx = 0;
for (bctbx_list_t *itm = other_participants; itm; itm = bctbx_list_next(itm)) {
LinphoneCoreManager *m = reinterpret_cast<LinphoneCoreManager *>(bctbx_list_get_data(itm));
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_NotifyReceived,
(other_participants_initial_stats[idx].number_of_NotifyReceived + 2), 5000));
idx++;
}
}
// Number of subscription errors should not change as the participants should received a notification
BC_ASSERT_EQUAL(conf_mgr->stat.number_of_LinphoneSubscriptionError,
initial_conf_stats.number_of_LinphoneSubscriptionError, int, "%0d");
BC_ASSERT_EQUAL(participant_mgr->stat.number_of_LinphoneSubscriptionError,
initial_participant_stats.number_of_LinphoneSubscriptionError, int, "%0d");
// Number of subscription terminated should not change as the participants should received a notification
BC_ASSERT_EQUAL(conf_mgr->stat.number_of_LinphoneSubscriptionTerminated,
initial_conf_stats.number_of_LinphoneSubscriptionTerminated, int, "%d");
BC_ASSERT_EQUAL(participant_mgr->stat.number_of_LinphoneSubscriptionTerminated,
initial_participant_stats.number_of_LinphoneSubscriptionTerminated, int, "%d");
int increment = 0;
if (participantSize == 0) {
// Also me is added as participant
increment = 2;
} else {
increment = 1;
}
BC_ASSERT_EQUAL((int)confListener->participants.size(), (participantSize + increment), int, "%d");
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), (participantDeviceSize + increment), int, "%d");
if (participantCall) {
const LinphoneAddress *cParticipantAddress = linphone_call_get_to_address(participantCall);
std::string participantUri =
Address::toCpp(const_cast<LinphoneAddress *>(cParticipantAddress))->asStringUriOnly();
BC_ASSERT_TRUE(confListener->participants.find(participantUri) != confListener->participants.end());
// Admin check
BC_ASSERT_TRUE(!confListener->participants.find(participantUri)->second);
}
if (other_participants_initial_stats) {
ms_free(other_participants_initial_stats);
}
if (other_participants) {
bctbx_list_free(other_participants);
}
return participantCall;
}
1821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890
LinphoneCoreManager *create_core_and_add_to_conference(const char *rc_file,
bctbx_list_t **mgrs,
bctbx_list_t **lcs,
std::shared_ptr<ConferenceListenerInterfaceTester> &confListener,
shared_ptr<MediaConference::LocalConference> &conf,
LinphoneCoreManager *conf_mgr,
bool_t pause_call) {
LinphoneCoreManager *mgr = create_mgr_for_conference(rc_file, TRUE, NULL);
*lcs = bctbx_list_append(*lcs, mgr->lc);
add_participant_to_conference_through_call(mgrs, *lcs, confListener, conf, conf_mgr, mgr, pause_call);
return mgr;
}
void send_added_notify_through_call() {
LinphoneCoreManager *pauline = create_mgr_for_conference(
transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", TRUE, NULL);
LinphoneCoreManager *marie = NULL;
LinphoneCoreManager *laure = NULL;
bctbx_list_t *lcs = NULL;
lcs = bctbx_list_append(lcs, pauline->lc);
bctbx_list_t *mgrs = NULL;
mgrs = bctbx_list_append(mgrs, pauline);
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
stats initialPaulineStats = pauline->stat;
{
shared_ptr<MediaConference::LocalConference> localConf = std::shared_ptr<MediaConference::LocalConference>(
new MediaConference::LocalConference(pauline->lc->cppPtr, addr, nullptr,
ConferenceParams::create(pauline->lc)),
[](MediaConference::LocalConference *c) { c->unref(); });
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneConferenceStateCreationPending,
initialPaulineStats.number_of_LinphoneConferenceStateCreationPending + 1, 5000));
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
// Add participants
// call not paused
marie = create_core_and_add_to_conference("marie_rc", &mgrs, &lcs, confListener, localConf, pauline, FALSE);
// call paused
laure =
create_core_and_add_to_conference((liblinphone_tester_ipv6_available()) ? "laure_tcp_rc" : "laure_rc_udp",
&mgrs, &lcs, confListener, localConf, pauline, TRUE);
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneConferenceStateCreated, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneConferenceStateCreated,
initialPaulineStats.number_of_LinphoneConferenceStateCreated + 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneConferenceStateCreated, 1, 5000));
localConf->terminate();
for (bctbx_list_t *it = mgrs; it; it = bctbx_list_next(it)) {
LinphoneCoreManager *m = reinterpret_cast<LinphoneCoreManager *>(bctbx_list_get_data(it));
// Wait for all calls to be terminated
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneCallEnd,
(int)bctbx_list_size(linphone_core_get_calls(m->lc)), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneCallReleased,
(int)bctbx_list_size(linphone_core_get_calls(m->lc)), 5000));
// Wait for all conferences to be terminated
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneConferenceStateTerminationPending,
m->stat.number_of_LinphoneConferenceStateCreated, 5000));
1891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneConferenceStateTerminated,
m->stat.number_of_LinphoneConferenceStateCreated, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneConferenceStateDeleted,
m->stat.number_of_LinphoneConferenceStateCreated, 5000));
}
}
destroy_mgr_in_conference(marie);
destroy_mgr_in_conference(pauline);
destroy_mgr_in_conference(laure);
bctbx_list_free(lcs);
bctbx_list_free(mgrs);
}
void send_removed_notify_through_call() {
LinphoneCoreManager *pauline = create_mgr_for_conference(
transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", TRUE, NULL);
LinphoneCoreManager *marie = NULL;
LinphoneCoreManager *laure = NULL;
LinphoneCoreManager *chloe = NULL;
bctbx_list_t *lcs = NULL;
lcs = bctbx_list_append(lcs, pauline->lc);
bctbx_list_t *participants_mgrs = NULL;
participants_mgrs = bctbx_list_append(participants_mgrs, pauline);
bctbx_list_t *removed_mgrs = NULL;
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
stats initialPaulineStats = pauline->stat;
{
shared_ptr<MediaConference::LocalConference> localConf = std::shared_ptr<MediaConference::LocalConference>(
new MediaConference::LocalConference(pauline->lc->cppPtr, addr, nullptr,
ConferenceParams::create(pauline->lc)),
[](MediaConference::LocalConference *c) { c->unref(); });
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneConferenceStateCreationPending,
initialPaulineStats.number_of_LinphoneConferenceStateCreationPending + 1, 5000));
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
// Add participants
marie = create_core_and_add_to_conference("marie_rc", &participants_mgrs, &lcs, confListener, localConf,
pauline, FALSE);
chloe = create_core_and_add_to_conference("chloe_rc", &participants_mgrs, &lcs, confListener, localConf,
pauline, FALSE);
laure =
create_core_and_add_to_conference((liblinphone_tester_ipv6_available()) ? "laure_tcp_rc" : "laure_rc_udp",
&participants_mgrs, &lcs, confListener, localConf, pauline, TRUE);
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneConferenceStateCreated, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneConferenceStateCreated,
initialPaulineStats.number_of_LinphoneConferenceStateCreated + 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneConferenceStateCreated, 1, 5000));
for (bctbx_list_t *it = participants_mgrs; it; it = bctbx_list_next(it)) {
LinphoneCoreManager *m = reinterpret_cast<LinphoneCoreManager *>(bctbx_list_get_data(it));
LinphoneCall *pCall = linphone_core_get_current_call(m->lc);
if (m == pauline) {
BC_ASSERT_PTR_NULL(pCall);
} else {
BC_ASSERT_PTR_NOT_NULL(pCall);
}
}
remove_head_participant_list_from_conference_through_call(&removed_mgrs, &participants_mgrs, lcs, confListener,
1961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030
localConf, pauline);
localConf->terminate();
for (bctbx_list_t *it = removed_mgrs; it; it = bctbx_list_next(it)) {
LinphoneCoreManager *m = reinterpret_cast<LinphoneCoreManager *>(bctbx_list_get_data(it));
LinphoneCall *call = linphone_core_get_current_call(m->lc);
if (call) {
linphone_call_terminate(call);
}
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneCallEnd,
(int)bctbx_list_size(linphone_core_get_calls(m->lc)), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneCallReleased,
(int)bctbx_list_size(linphone_core_get_calls(m->lc)), 5000));
}
for (bctbx_list_t *it = participants_mgrs; it; it = bctbx_list_next(it)) {
LinphoneCoreManager *m = reinterpret_cast<LinphoneCoreManager *>(bctbx_list_get_data(it));
// Wait for all calls to be terminated
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneCallEnd,
(int)bctbx_list_size(linphone_core_get_calls(m->lc)), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneCallReleased,
(int)bctbx_list_size(linphone_core_get_calls(m->lc)), 5000));
// Wait for all conferences to be terminated
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneConferenceStateTerminationPending,
m->stat.number_of_LinphoneConferenceStateCreated, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneConferenceStateTerminated,
m->stat.number_of_LinphoneConferenceStateCreated, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &m->stat.number_of_LinphoneConferenceStateDeleted,
m->stat.number_of_LinphoneConferenceStateCreated, 5000));
}
}
if (marie) destroy_mgr_in_conference(marie);
if (pauline) destroy_mgr_in_conference(pauline);
if (laure) destroy_mgr_in_conference(laure);
if (chloe) destroy_mgr_in_conference(chloe);
bctbx_list_free(lcs);
bctbx_list_free(participants_mgrs);
bctbx_list_free(removed_mgrs);
}
void send_removed_notify() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
shared_ptr<LocalConferenceTester> localConf =
make_shared<LocalConferenceTester>(pauline->lc->cppPtr, addr, nullptr);
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri);
std::shared_ptr<Address> bobAddr = Address::toCpp(cBobAddr)->getSharedFromThis();
linphone_address_unref(cBobAddr);
LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
std::shared_ptr<Address> aliceAddr = Address::toCpp(cAliceAddr)->getSharedFromThis();
linphone_address_unref(cAliceAddr);
localConf->addParticipant(bobAddr);
localConf->addParticipant(aliceAddr);
setParticipantAsAdmin(localConf, aliceAddr, true);
localConf->setConferenceAddress(addr);
BC_ASSERT_EQUAL((int)confListener->participants.size(), 2, int, "%d");
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
// Admin check
2031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
unsigned int lastNotifyCount = confListener->lastNotify;
localConf->notifyParticipantRemoved(time(nullptr), false, localConf->findParticipant(bobAddr));
BC_ASSERT_EQUAL((int)confListener->participants.size(), 1, int, "%d");
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), 1, int, "%d");
BC_ASSERT_FALSE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
// Admin check
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
BC_ASSERT_EQUAL(localConf->getLastNotify(), (lastNotifyCount + 1), int, "%d");
localConf = nullptr;
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
void send_admined_notify() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
shared_ptr<LocalConferenceTester> localConf =
make_shared<LocalConferenceTester>(pauline->lc->cppPtr, addr, nullptr);
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri);
std::shared_ptr<Address> bobAddr = Address::toCpp(cBobAddr)->getSharedFromThis();
linphone_address_unref(cBobAddr);
LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
std::shared_ptr<Address> aliceAddr = Address::toCpp(cAliceAddr)->getSharedFromThis();
linphone_address_unref(cAliceAddr);
localConf->addParticipant(bobAddr);
localConf->addParticipant(aliceAddr);
setParticipantAsAdmin(localConf, aliceAddr, true);
localConf->setConferenceAddress(addr);
BC_ASSERT_EQUAL((int)confListener->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
// Admin check
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
unsigned int lastNotifyCount = confListener->lastNotify;
localConf->notifyParticipantSetAdmin(time(nullptr), false, localConf->findParticipant(bobAddr), true);
BC_ASSERT_EQUAL((int)confListener->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
// Admin check
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_EQUAL(localConf->getLastNotify(), (lastNotifyCount + 1), int, "%d");
localConf = nullptr;
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
void send_unadmined_notify() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline =
2101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
shared_ptr<LocalConferenceTester> localConf =
make_shared<LocalConferenceTester>(pauline->lc->cppPtr, addr, nullptr);
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri);
std::shared_ptr<Address> bobAddr = Address::toCpp(cBobAddr)->getSharedFromThis();
linphone_address_unref(cBobAddr);
LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
std::shared_ptr<Address> aliceAddr = Address::toCpp(cAliceAddr)->getSharedFromThis();
linphone_address_unref(cAliceAddr);
localConf->addParticipant(bobAddr);
localConf->addParticipant(aliceAddr);
setParticipantAsAdmin(localConf, aliceAddr, true);
localConf->setConferenceAddress(addr);
BC_ASSERT_EQUAL((int)confListener->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
// Admin check
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
unsigned int lastNotifyCount = confListener->lastNotify;
localConf->notifyParticipantSetAdmin(time(nullptr), false, localConf->findParticipant(aliceAddr), false);
BC_ASSERT_EQUAL((int)confListener->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
// Admin check
BC_ASSERT_TRUE(!confListener->participants.find(aliceAddr->toString())->second);
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_EQUAL(localConf->getLastNotify(), (lastNotifyCount + 1), int, "%d");
localConf = nullptr;
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
void send_subject_changed_notify() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
shared_ptr<LocalConferenceTester> localConf =
make_shared<LocalConferenceTester>(pauline->lc->cppPtr, addr, nullptr);
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri);
std::shared_ptr<Address> bobAddr = Address::toCpp(cBobAddr)->getSharedFromThis();
linphone_address_unref(cBobAddr);
LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri);
std::shared_ptr<Address> aliceAddr = Address::toCpp(cAliceAddr)->getSharedFromThis();
linphone_address_unref(cAliceAddr);
localConf->addParticipant(bobAddr);
localConf->addParticipant(aliceAddr);
localConf->setSubject("A random test subject");
setParticipantAsAdmin(localConf, aliceAddr, true);
localConf->setConferenceAddress(addr);
BC_ASSERT_STRING_EQUAL(confListener->confSubject.c_str(), "A random test subject");
BC_ASSERT_EQUAL((int)confListener->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
// Admin check
2171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
unsigned int lastNotifyCount = confListener->lastNotify;
localConf->setSubject("Another random test subject...");
BC_ASSERT_STRING_EQUAL(confListener->confSubject.c_str(), "Another random test subject...");
BC_ASSERT_EQUAL((int)confListener->participants.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participants.find(bobAddr->toString()) != confListener->participants.end());
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString()) != confListener->participants.end());
// Admin check
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
BC_ASSERT_EQUAL(localConf->getLastNotify(), (lastNotifyCount + 1), int, "%d");
localConf = nullptr;
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
void send_device_added_notify() {
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
linphone_core_cbs_set_notify_sent(cbs, linphone_notify_sent);
_linphone_core_add_callbacks(pauline->lc, cbs, TRUE);
linphone_core_cbs_unref(cbs);
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
shared_ptr<LocalConferenceTester> localConf =
make_shared<LocalConferenceTester>(pauline->lc->cppPtr, addr, nullptr);
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
LinphoneAddress *cBobAddr = linphone_core_interpret_url(pauline->lc, bobUri);
std::shared_ptr<Address> bobAddr = Address::toCpp(cBobAddr)->getSharedFromThis();
linphone_address_unref(cBobAddr);
LinphoneAddress *cAliceAddr = linphone_core_interpret_url(pauline->lc, aliceUri);
std::shared_ptr<Address> aliceAddr = Address::toCpp(cAliceAddr)->getSharedFromThis();
linphone_address_unref(cAliceAddr);
localConf->addParticipant(bobAddr);
localConf->addParticipant(aliceAddr);
shared_ptr<Participant> alice = localConf->findParticipant(aliceAddr);
setParticipantAsAdmin(localConf, aliceAddr, true);
localConf->setConferenceAddress(addr);
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participantDevices.find(bobAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_TRUE(confListener->participantDevices.find(aliceAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_EQUAL(confListener->participantDevices.find(bobAddr->toString())->second, 0, int, "%d");
BC_ASSERT_EQUAL(confListener->participantDevices.find(aliceAddr->toString())->second, 0, int, "%d");
// Admin check
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
localConf->notifyParticipantDeviceAdded(time(nullptr), false, alice, alice->findDevice(aliceAddr));
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participantDevices.find(bobAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_TRUE(confListener->participantDevices.find(aliceAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_EQUAL(confListener->participantDevices.find(bobAddr->toString())->second, 0, int, "%d");
BC_ASSERT_EQUAL(confListener->participantDevices.find(aliceAddr->toString())->second, 1, int, "%d");
// Admin check
BC_ASSERT_TRUE(!confListener->participants.find(bobAddr->toString())->second);
2241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310
BC_ASSERT_TRUE(confListener->participants.find(aliceAddr->toString())->second);
for (const auto &p : localConf->getParticipants()) {
for (const auto &d : p->getDevices()) {
linphone_participant_device_set_state(d->toC(), LinphoneParticipantDeviceStatePresent);
}
}
stats initial_pauline_stats = pauline->stat;
auto op = new SalSubscribeOp(pauline->lc->sal.get());
SalAddress *toAddr = sal_address_new(linphone_core_get_identity(pauline->lc));
op->setToAddress(toAddr);
op->setFrom(bobAddr->toString().c_str());
op->overrideRemoteContact(bobAddr->toString().c_str());
LinphoneAccount *default_account = linphone_core_get_default_account(pauline->lc);
op->setRealm(linphone_account_params_get_realm(linphone_account_get_params(default_account)));
const LinphoneAddress *contact = linphone_account_get_contact_address(default_account);
SalAddress *contactAddr = sal_address_clone(Address::toCpp(const_cast<LinphoneAddress *>(contact))->getImpl());
op->setContactAddress(contactAddr);
SalCustomHeader *ch =
sal_custom_header_append(NULL, "Last-Notify-Version", std::to_string(localConf->getLastNotify() + 10).c_str());
op->setRecvCustomHeaders(ch);
LinphoneEvent *lev =
linphone_event_new_subscribe_with_op(pauline->lc, op, LinphoneSubscriptionIncoming, "conference");
linphone_event_set_state(lev, LinphoneSubscriptionIncomingReceived);
localConf->subscribeReceived(dynamic_pointer_cast<EventSubscribe>(Event::toCpp(lev)->getSharedFromThis()));
linphone_event_unref(lev);
sal_address_unref(toAddr);
sal_address_unref(contactAddr);
sal_custom_header_unref(ch);
BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_NotifySent,
(initial_pauline_stats.number_of_NotifySent + 1), 5000));
void *notify_body = linphone_event_get_user_data(lev);
BC_ASSERT_PTR_NOT_NULL(notify_body);
if (notify_body) {
LinphoneContent *notify_content = (LinphoneContent *)notify_body;
BC_ASSERT_STRING_EQUAL(linphone_content_get_type(notify_content), "application");
BC_ASSERT_STRING_EQUAL(linphone_content_get_subtype(notify_content), "conference-info+xml");
BC_ASSERT_TRUE(linphone_conference_type_is_full_state(linphone_content_get_utf8_text(notify_content)));
linphone_content_unref(notify_content);
}
localConf = nullptr;
alice = nullptr;
linphone_core_manager_destroy(pauline);
}
void send_device_removed_notify() {
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
shared_ptr<LocalConferenceTester> localConf =
make_shared<LocalConferenceTester>(pauline->lc->cppPtr, addr, nullptr);
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
LinphoneAddress *cBobAddr = linphone_core_interpret_url(pauline->lc, bobUri);
std::shared_ptr<Address> bobAddr = Address::toCpp(cBobAddr)->getSharedFromThis();
linphone_address_unref(cBobAddr);
LinphoneAddress *cAliceAddr = linphone_core_interpret_url(pauline->lc, aliceUri);
std::shared_ptr<Address> aliceAddr = Address::toCpp(cAliceAddr)->getSharedFromThis();
linphone_address_unref(cAliceAddr);
localConf->addParticipant(bobAddr);
localConf->addParticipant(aliceAddr);
2311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380
localConf->setSubject("A random test subject");
shared_ptr<Participant> alice = localConf->findParticipant(aliceAddr);
setParticipantAsAdmin(localConf, aliceAddr, true);
localConf->setConferenceAddress(addr);
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participantDevices.find(bobAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_TRUE(confListener->participantDevices.find(aliceAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_EQUAL(confListener->participantDevices.find(bobAddr->toString())->second, 0, int, "%d");
BC_ASSERT_EQUAL(confListener->participantDevices.find(aliceAddr->toString())->second, 0, int, "%d");
localConf->notifyParticipantDeviceAdded(time(nullptr), false, alice, alice->findDevice(aliceAddr));
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participantDevices.find(bobAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_TRUE(confListener->participantDevices.find(aliceAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_EQUAL(confListener->participantDevices.find(bobAddr->toString())->second, 0, int, "%d");
BC_ASSERT_EQUAL(confListener->participantDevices.find(aliceAddr->toString())->second, 1, int, "%d");
localConf->notifyParticipantDeviceRemoved(time(nullptr), false, alice, alice->findDevice(aliceAddr));
BC_ASSERT_EQUAL((int)confListener->participantDevices.size(), 2, int, "%d");
BC_ASSERT_TRUE(confListener->participantDevices.find(bobAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_TRUE(confListener->participantDevices.find(aliceAddr->toString()) !=
confListener->participantDevices.end());
BC_ASSERT_EQUAL(confListener->participantDevices.find(bobAddr->toString())->second, 0, int, "%d");
BC_ASSERT_EQUAL(confListener->participantDevices.find(aliceAddr->toString())->second, 0, int, "%d");
localConf = nullptr;
alice = nullptr;
linphone_core_manager_destroy(pauline);
}
void one_to_one_keyword() {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
std::shared_ptr<Address> addr = Address::toCpp(pauline->identity)->getSharedFromThis();
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
shared_ptr<LocalConference> localConf =
make_shared<LocalConference>(pauline->lc->cppPtr, addr, nullptr, ConferenceParams::create(pauline->lc));
std::shared_ptr<ConferenceListenerInterfaceTester> confListener =
std::make_shared<ConferenceListenerInterfaceTester>();
localConf->addListener(confListener);
LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri);
std::shared_ptr<Address> bobAddr = Address::toCpp(cBobAddr)->getSharedFromThis();
linphone_address_unref(cBobAddr);
// Create basic chat room with OneToOne capability to ensure that one to one is added to notify
pauline->lc->cppPtr->getOrCreateBasicChatRoom(addr, addr);
localConf->addParticipant(bobAddr);
LocalConferenceEventHandler *localHandler = (L_ATTR_GET(localConf.get(), eventHandler)).get();
localConf->setConferenceAddress(addr);
Content content = localHandler->createNotifyFullState(NULL);
const_cast<ConferenceId &>(tester->handler->getConferenceId()).setPeerAddress(addr);
tester->handler->notifyReceived(content);
BC_ASSERT_EQUAL((int)tester->participantDevices.size(), 1, int, "%d");
BC_ASSERT_TRUE(tester->participantDevices.find(bobAddr->toString()) != tester->participantDevices.end());
BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddr->toString())->second, 0, int, "%d");
BC_ASSERT_TRUE(tester->oneToOne);
238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416
tester = nullptr;
localConf = nullptr;
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
test_t conference_event_tests[] = {
TEST_NO_TAG("First notify parsing", first_notify_parsing),
TEST_NO_TAG("First notify with extensions parsing", first_notify_with_extensions_parsing),
TEST_NO_TAG("First notify parsing wrong conf", first_notify_parsing_wrong_conf),
TEST_NO_TAG("Participant added", participant_added_parsing),
TEST_NO_TAG("Participant not added", participant_not_added_parsing),
TEST_NO_TAG("Participant deleted", participant_deleted_parsing),
TEST_NO_TAG("Participant admined", participant_admined_parsing),
TEST_NO_TAG("Participant unadmined", participant_unadmined_parsing),
TEST_NO_TAG("Send first notify", send_first_notify),
TEST_NO_TAG("Send participant added notify through address", send_added_notify_through_address),
TEST_NO_TAG("Send participant added notify through call", send_added_notify_through_call),
TEST_NO_TAG("Send participant removed notify through call", send_removed_notify_through_call),
TEST_NO_TAG("Send participant removed notify", send_removed_notify),
TEST_NO_TAG("Send participant admined notify", send_admined_notify),
TEST_NO_TAG("Send participant unadmined notify", send_unadmined_notify),
TEST_NO_TAG("Send subject changed notify", send_subject_changed_notify),
TEST_NO_TAG("Send device added notify", send_device_added_notify),
TEST_NO_TAG("Send device removed notify", send_device_removed_notify),
TEST_NO_TAG("one-to-one keyword", one_to_one_keyword)};
test_suite_t conference_event_test_suite = {"Conference event",
nullptr,
nullptr,
liblinphone_tester_before_each,
liblinphone_tester_after_each,
sizeof(conference_event_tests) / sizeof(conference_event_tests[0]),
conference_event_tests,
0};