diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index fb380c2a5..7e46275bf 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -156,6 +156,9 @@ if (ENABLE_STATIC) ) target_include_directories(linphone-coreapi-static SYSTEM PRIVATE ${LINPHONE_INCLUDE_DIRS}) add_dependencies(linphone-coreapi-static liblinphone-git-version) + if (ENABLE_JAVA_WRAPPER) + add_dependencies(linphone-coreapi-static linphonej) + endif() endif () if (ENABLE_SHARED) @@ -165,6 +168,9 @@ if (ENABLE_SHARED) target_include_directories(linphone-coreapi SYSTEM PRIVATE ${LINPHONE_INCLUDE_DIRS}) target_compile_options(linphone-coreapi PRIVATE "-fPIC") add_dependencies(linphone-coreapi liblinphone-git-version) + if (ENABLE_JAVA_WRAPPER) + add_dependencies(linphone-coreapi linphonej) + endif() endif () diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 6205237d1..e5337abd6 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3738,7 +3738,7 @@ static LinphoneCall * get_unique_call(LinphoneCore *lc) { return call; } -LinphoneStatus linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) { +static LinphoneStatus _linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) { if (call == NULL) { call = get_unique_call(lc); if (call == NULL) { @@ -3750,7 +3750,11 @@ LinphoneStatus linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneC } LinphoneStatus linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) { - return linphone_core_accept_call_with_params(lc, call, NULL); + return _linphone_core_accept_call_with_params(lc, call, NULL); +} + +LinphoneStatus linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) { + return _linphone_core_accept_call_with_params(lc, call, params); } LinphoneStatus linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri) { diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 225a6c13e..3c289a42b 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -135,8 +135,12 @@ set(LINPHONE_HEADER_FILES ${ROOT_HEADER_FILES} ${C_API_HEADER_FILES} ${ENUMS_HEA set(LINPHONE_HEADER_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}" PARENT_SCOPE) # ------------------------------------------------------------------------------ - -set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_INCLUDEDIR}/linphone") +if (IOS AND ENABLE_SHARED) + #cmake 3.10 seems not able to handle subdirectories for PUBLIC_HEADER. My be rework in the futur + set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_PREFIX}/Frameworks/linphone.framework/Headers") +else() + set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_INCLUDEDIR}/linphone") +endif() install(FILES ${ROOT_HEADER_FILES} DESTINATION "${DEST_ROOT_DIRECTORY}" diff --git a/include/linphone/utils/static-string.h b/include/linphone/utils/static-string.h index ae65f6668..bbc421e06 100644 --- a/include/linphone/utils/static-string.h +++ b/include/linphone/utils/static-string.h @@ -111,13 +111,17 @@ namespace Private { RawStaticString raw; private: - template= 0, int>::type* = nullptr> - constexpr StaticIntStringHelper (const IndexSequence &) : - raw{ char('0' + Value / pow10(N - Index - 2) % 10 )..., '\0' } {} + // Workaround for MSVC 2015. + // See: https://stackoverflow.com/questions/41593649/why-wont-visual-studio-let-me-use-a-templatized-constexpr-function-in-enable-i/41597153 + struct IsNeg { static const bool value = Value < 0; }; - template::type* = nullptr> + template::type* = nullptr> constexpr StaticIntStringHelper (const IndexSequence &) : - raw{ '-', char('0' + abs(Value) / pow10(N - Index - 3) % 10 )..., '\0' } {} + raw{ char('0' + Value / pow10(N - Index - 2) % 10)..., '\0' } {} + + template::type* = nullptr> + constexpr StaticIntStringHelper(const IndexSequence &) : + raw{ '-', char('0' + abs(Value) / pow10(N - Index - 3) % 10)..., '\0' } {} }; }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 990974b2c..d05cfd3a9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -417,7 +417,6 @@ if(ENABLE_SHARED) FRAMEWORK TRUE MACOSX_FRAMEWORK_IDENTIFIER org.linphone.linphone MACOSX_FRAMEWORK_INFO_PLIST Info.plist.in - PUBLIC_HEADER "${LINPHONE_HEADER_FILES}" RESOURCE "../share/cpim_grammar" ) endif() @@ -441,9 +440,6 @@ if(ENABLE_SHARED) set_target_properties(linphone PROPERTIES PREFIX "lib") elseif(ANDROID) target_link_libraries(linphone PUBLIC "log" ${SUPPORT_LIBRARIES} ${CPUFEATURES_LIBRARIES}) - if(ENABLE_JAVA_WRAPPER) - add_dependencies(linphone linphonej) - endif() endif() if(MSVC) if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp index 6b70da34d..aaecdf469 100644 --- a/src/chat/chat-room/chat-room.cpp +++ b/src/chat/chat-room/chat-room.cpp @@ -196,10 +196,13 @@ void ChatRoomPrivate::notifyChatMessageReceived (const shared_ptr & void ChatRoomPrivate::notifyIsComposingReceived (const Address &remoteAddress, bool isComposing) { L_Q(); - if (isComposing) - remoteIsComposing.push_back(remoteAddress); - else + if (isComposing) { + auto it = find(remoteIsComposing.cbegin(), remoteIsComposing.cend(), remoteAddress); + if (it == remoteIsComposing.cend()) + remoteIsComposing.push_back(remoteAddress); + } else { remoteIsComposing.remove(remoteAddress); + } LinphoneChatRoom *cr = getCChatRoom(); LinphoneAddress *lAddr = linphone_address_new(remoteAddress.asString().c_str()); diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index c0d1741d8..8e0b1025e 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -1145,47 +1145,55 @@ string MediaSessionPrivate::getBindIpForStream (int streamIndex) { */ void MediaSessionPrivate::getLocalIp (const Address &remoteAddr) { L_Q(); - /* Next, sometime, override from config */ - const char *ip = lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "bind_address", nullptr); + // Next, sometime, override from config + const char *ip = linphone_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "bind_address", nullptr); if (ip) { mediaLocalIp = ip; return; } - /* If a known proxy was identified for this call, then we may have a chance to take the local ip address - * from the socket that connects to this proxy */ + // If a known proxy was identified for this call, then we may have a chance to take the local ip address + // from the socket that connects to this proxy if (destProxy && destProxy->op) { ip = destProxy->op->getLocalAddress(nullptr); if (ip) { - lInfo() << "Found media local-ip from signaling."; - mediaLocalIp = ip; - return; + if (strchr(ip, ':') && (af == AF_INET)) { + // Case where we've decided to use IPv4 in selectOutgoingIpVersion(), but the signaling local ip address is IPv6. + // We'll use the default media localip + } else { + lInfo() << "Found media local-ip from signaling."; + mediaLocalIp = ip; + return; + } } } - /* In last resort, attempt to find the local ip that routes to destination if given as an IP address, - or the default route (dest == nullptr) */ - const char *dest = nullptr; + // In last resort, attempt to find the local ip that routes to destination if given as an IP address, + // or the default route (dest is empty) + string dest; if (!destProxy) { struct addrinfo hints; struct addrinfo *res = nullptr; + string host(remoteAddr.getDomain()); int err; - /* FIXME the following doesn't work for IPv6 address because of brakets */ + + if (host[0] == '[') + host = host.substr(1, host.size() - 2); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_NUMERICHOST; - err = getaddrinfo(remoteAddr.getDomain().c_str(), nullptr, &hints, &res); + err = getaddrinfo(host.c_str(), nullptr, &hints, &res); if (err == 0) - dest = remoteAddr.getDomain().c_str(); - if (res) freeaddrinfo(res); + dest = host; // The remote address host part is real ip address, use it + if (res) + freeaddrinfo(res); } - if (dest || mediaLocalIp.empty() || needMediaLocalIpRefresh) { + if (!dest.empty() || mediaLocalIp.empty() || needMediaLocalIpRefresh) { needMediaLocalIpRefresh = false; - char ip[LINPHONE_IPADDR_SIZE]; - linphone_core_get_local_ip(q->getCore()->getCCore(), af, dest, ip); - mediaLocalIp = ip; + mediaLocalIp.reserve(LINPHONE_IPADDR_SIZE); + linphone_core_get_local_ip(q->getCore()->getCCore(), af, dest.c_str(), &mediaLocalIp[0]); } } @@ -1227,44 +1235,44 @@ void MediaSessionPrivate::selectIncomingIpVersion () { * Choose IP version we are going to use for RTP streams IP address advertised in SDP. * The algorithm is as follows: * - if ipv6 is disabled at the core level, it is always AF_INET - * - Otherwise, if the destination address for the call is an IPv6 address, use IPv6. * - Otherwise, if the call is done through a known proxy config, then use the information obtained during REGISTER + * - Otherwise if the destination address for the call is an IPv6 address, use IPv6. * to know if IPv6 is supported by the server. **/ void MediaSessionPrivate::selectOutgoingIpVersion () { L_Q(); - if (!linphone_core_ipv6_enabled(q->getCore()->getCCore())) { - af = AF_INET; - return; - } + char ipv4[LINPHONE_IPADDR_SIZE]; + char ipv6[LINPHONE_IPADDR_SIZE]; + bool haveIpv6 = false; + bool haveIpv4 = false; + + af = AF_UNSPEC; + if (linphone_core_get_local_ip_for(AF_INET, nullptr, ipv4) == 0) + haveIpv4 = true; + if (linphone_core_ipv6_enabled(q->getCore()->getCCore())) { + const LinphoneAddress *to = linphone_call_log_get_to_address(log); - const LinphoneAddress *to = linphone_call_log_get_to_address(log); - if (sal_address_is_ipv6(L_GET_PRIVATE_FROM_C_OBJECT(to)->getInternalAddress())) - af = AF_INET6; - else if (destProxy && destProxy->op) - af = destProxy->op->getAddressFamily(); - else { - char ipv4[LINPHONE_IPADDR_SIZE]; - char ipv6[LINPHONE_IPADDR_SIZE]; - bool haveIpv6 = false; - bool haveIpv4 = false; - /* Check connectivity for IPv4 and IPv6 */ if (linphone_core_get_local_ip_for(AF_INET6, nullptr, ipv6) == 0) haveIpv6 = true; - if (linphone_core_get_local_ip_for(AF_INET, nullptr, ipv4) == 0) - haveIpv4 = true; - if (haveIpv6) { - if (!haveIpv4) - af = AF_INET6; - else if (lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "prefer_ipv6", 1)) /* This property tells whether ipv6 is prefered if two versions are available */ - af = AF_INET6; - else - af = AF_INET; - } else - af = AF_INET; - /* Fill the media_localip default value since we have it here */ - mediaLocalIp = (af == AF_INET6) ? ipv6 : ipv4; + if (destProxy && destProxy->op) { + // We can determine from the proxy connection whether IPv6 works - this is the most reliable + af = destProxy->op->getAddressFamily(); + } else if (sal_address_is_ipv6(L_GET_PRIVATE_FROM_C_OBJECT(to)->getInternalAddress())) { + af = AF_INET6; + } + + if (!linphone_config_get_bool(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "prefer_ipv6", TRUE) && haveIpv4) { + // This is the case where IPv4 is to be prefered if both are available + af = AF_INET; // We'll use IPv4 + lInfo() << "prefer_ipv6 is set to false, as both IP versions are available we are going to use IPv4"; + } + if (af == AF_UNSPEC) + af = haveIpv6 ? AF_INET6 : AF_INET; + } else { + af = AF_INET; } + // Fill the media_localip default value since we have it here + mediaLocalIp = (af == AF_INET6) ? ipv6 : ipv4; } // ----------------------------------------------------------------------------- @@ -2178,8 +2186,7 @@ RtpSession * MediaSessionPrivate::createVideoRtpIoSession () { rtp_session_set_remote_addr_and_port(rtpSession, remoteIp, remotePort, -1); rtp_session_enable_rtcp(rtpSession, false); rtp_session_set_payload_type(rtpSession, ptnum); - bool symmetric = lp_config_get_int(config, "video", "rtp_symmetric", 0); - rtp_session_set_symmetric_rtp(rtpSession, symmetric); + rtp_session_set_symmetric_rtp(rtpSession, linphone_config_get_bool(config, "video", "rtp_symmetric", FALSE)); int jittcomp = lp_config_get_int(config, "video", "rtp_jittcomp", 0); /* 0 means no jitter buffer */ rtp_session_set_jitter_compensation(rtpSession, jittcomp); rtp_session_enable_jitter_buffer(rtpSession, (jittcomp > 0)); @@ -2921,7 +2928,7 @@ void MediaSessionPrivate::startVideoStream (CallSession::State targetState) { video_stream_use_preview_video_window(videoStream, q->getCore()->getCCore()->use_preview_window); const char *rtpAddr = (vstream->rtp_addr[0] != '\0') ? vstream->rtp_addr : resultDesc->addr; const char *rtcpAddr = (vstream->rtcp_addr[0] != '\0') ? vstream->rtcp_addr : resultDesc->addr; - bool isMulticast = ms_is_multicast(rtpAddr); + bool isMulticast = !!ms_is_multicast(rtpAddr); MediaStreamDir dir = MediaStreamSendRecv; bool isActive = true; if (isMulticast) { @@ -2975,8 +2982,7 @@ void MediaSessionPrivate::startVideoStream (CallSession::State targetState) { } else { bool ok = true; MSMediaStreamIO io = MS_MEDIA_STREAM_IO_INITIALIZER; - bool useRtpIo = lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "video", "rtp_io", false); - if (useRtpIo) { + if (linphone_config_get_bool(linphone_core_get_config(q->getCore()->getCCore()), "video", "rtp_io", FALSE)) { io.input.type = io.output.type = MSResourceRtp; io.input.session = io.output.session = createVideoRtpIoSession(); if (!io.input.session) { diff --git a/src/search/magic-search.cpp b/src/search/magic-search.cpp index 3c8c92379..ec051baca 100644 --- a/src/search/magic-search.cpp +++ b/src/search/magic-search.cpp @@ -151,6 +151,7 @@ list MagicSearch::getContactListFromFilter(const string &filter, c string filterAddress = "sip:" + filter + "@" + domain; LinphoneAddress *lastResult = linphone_core_create_address(this->getCore()->getCCore(), filterAddress.c_str()); if (lastResult) returnList.push_back(SearchResult(0, lastResult, "", nullptr)); + linphone_address_unref(lastResult); } } @@ -182,26 +183,39 @@ list MagicSearch::getAllFriends() { bctbx_list_t *lPhoneNumbers = linphone_friend_get_phone_numbers(lFriend); string lPhoneNumber = (lPhoneNumbers != nullptr) ? static_cast(lPhoneNumbers->data) : ""; - if (lAddress) linphone_address_ref(const_cast(lAddress)); returnList.push_back(SearchResult(1, lAddress, lPhoneNumber, lFriend)); } + returnList.sort([](const SearchResult& lsr, const SearchResult& rsr){ + unsigned int cpt = 0; + string name1 = linphone_friend_get_name(lsr.getFriend()); + string name2 = linphone_friend_get_name(rsr.getFriend()); + unsigned int char1 = tolower(name1.at(cpt)); + unsigned int char2 = tolower(name2.at(cpt)); + + while (name1.size() > cpt && name2.size() > cpt) { + if (char1 < char2) { + return true; + } else if (char1 > char2) { + return false; + } + cpt++; + } + return name1.size() < name2.size(); + }); + return returnList; } list *MagicSearch::beginNewSearch(const string &filter, const string &withDomain) { list *resultList = new list(); - LinphoneFriendList *list = linphone_core_get_default_friend_list(this->getCore()->getCCore()); + LinphoneFriendList *fList = linphone_core_get_default_friend_list(this->getCore()->getCCore()); const bctbx_list_t *callLog = linphone_core_get_call_logs(this->getCore()->getCCore()); // For all friends or when we reach the search limit - for (bctbx_list_t *f = list->friends ; f != nullptr ; f = bctbx_list_next(f)) { - SearchResult result = searchInFriend(reinterpret_cast(f->data), filter, withDomain); - if (result.getWeight() > getMinWeight()) { - if (result.getAddress() || !result.getPhoneNumber().empty()) { - resultList->push_back(result); - } - } + for (bctbx_list_t *f = fList->friends ; f != nullptr ; f = bctbx_list_next(f)) { + list results = searchInFriend(reinterpret_cast(f->data), filter, withDomain); + addResultsToResultsList(results, *resultList); } // For all call log or when we reach the search limit @@ -212,8 +226,6 @@ list *MagicSearch::beginNewSearch(const string &filter, const stri if (addr) { unsigned int weight = searchInAddress(addr, filter, withDomain); if (weight > getMinWeight()) { - // FIXME: Ugly temporary workaround to solve weak. Remove me later. - linphone_address_ref(const_cast(addr)); resultList->push_back(SearchResult(weight, addr, "", nullptr)); } } @@ -229,10 +241,8 @@ list *MagicSearch::continueSearch(const string &filter, const stri for (const auto sr : *cacheList) { if (sr.getAddress() || !sr.getPhoneNumber().empty()) { if (sr.getFriend()) { - SearchResult result = searchInFriend(sr.getFriend(), filter, withDomain); - if (result.getWeight() > getMinWeight()) { - resultList->push_back(result); - } + list results = searchInFriend(sr.getFriend(), filter, withDomain); + addResultsToResultsList(results, *resultList); } else { unsigned int weight = searchInAddress(sr.getAddress(), filter, withDomain); if (weight > getMinWeight()) { @@ -245,14 +255,10 @@ list *MagicSearch::continueSearch(const string &filter, const stri return resultList; } -SearchResult MagicSearch::searchInFriend(const LinphoneFriend *lFriend, const string &filter, const string &withDomain) { +list MagicSearch::searchInFriend(const LinphoneFriend *lFriend, const string &filter, const string &withDomain) { + list friendResult; string phoneNumber = ""; unsigned int weight = getMinWeight(); - const LinphoneAddress* lAddress = linphone_friend_get_address(lFriend); - - if (!checkDomain(lFriend, lAddress, withDomain)) { - if (!withDomain.empty()) return SearchResult(weight, nullptr, ""); - } // NAME if (linphone_core_vcard_supported()) { @@ -262,7 +268,22 @@ SearchResult MagicSearch::searchInFriend(const LinphoneFriend *lFriend, const st } //SIP URI - weight += searchInAddress(lAddress, filter, withDomain) * 1; + for (const bctbx_list_t *listAddress = linphone_friend_get_addresses(lFriend); + listAddress != nullptr && listAddress->data != nullptr; + listAddress = listAddress->next) { + const LinphoneAddress *lAddress = static_cast(listAddress->data); + if (!checkDomain(lFriend, lAddress, withDomain)) { + if (!withDomain.empty()) { + continue; + } + } + + unsigned int weightAddress = searchInAddress(lAddress, filter, withDomain) * 1; + + if ((weightAddress + weight) > getMinWeight()) { + friendResult.push_back(SearchResult(weight + weightAddress, lAddress, phoneNumber, lFriend)); + } + } // PHONE NUMBER LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(this->getCore()->getCCore()); @@ -273,21 +294,24 @@ SearchResult MagicSearch::searchInFriend(const LinphoneFriend *lFriend, const st const LinphonePresenceModel *presence = linphone_friend_get_presence_model_for_uri_or_tel(lFriend, number.c_str()); phoneNumber = number; if (proxy) { - phoneNumber = linphone_proxy_config_normalize_phone_number(proxy, phoneNumber.c_str()); + char * buff = linphone_proxy_config_normalize_phone_number(proxy, phoneNumber.c_str()); + phoneNumber = buff; + bctbx_free(buff); } - weight += getWeight(phoneNumber.c_str(), filter); + unsigned int weightNumber = getWeight(phoneNumber.c_str(), filter); if (presence) { char *contact = linphone_presence_model_get_contact(presence); - weight += getWeight(contact, filter) * 2; + weightNumber += getWeight(contact, filter) * 2; bctbx_free(contact); } + if (weightNumber > getMinWeight()) { + friendResult.push_back(SearchResult(weight + weightNumber, linphone_friend_get_address(lFriend), phoneNumber, lFriend)); + } phoneNumbers = phoneNumbers->next; } if (begin) bctbx_list_free(begin); - // FIXME: Ugly temporary workaround to solve weak. Remove me later. - if (lAddress) linphone_address_ref(const_cast(lAddress)); - return SearchResult(weight, lAddress, phoneNumber, lFriend); + return friendResult; } unsigned int MagicSearch::searchInAddress(const LinphoneAddress *lAddress, const string &filter, const string &withDomain) { @@ -371,4 +395,12 @@ bool MagicSearch::checkDomain(const LinphoneFriend *lFriend, const LinphoneAddre return soFarSoGood; } +void MagicSearch::addResultsToResultsList(std::list &results, std::list &srL) { + if (results.size() > 0) { + for (auto r : results) { + srL.push_back(r); + } + } +} + LINPHONE_END_NAMESPACE diff --git a/src/search/magic-search.h b/src/search/magic-search.h index 7020405c0..ac6a30e30 100644 --- a/src/search/magic-search.h +++ b/src/search/magic-search.h @@ -168,9 +168,10 @@ private: * @param[in] lFriend friend whose informations will be check * @param[in] filter word we search * @param[in] withDomain domain which we want to search only + * @return list of result from friend * @private **/ - SearchResult searchInFriend(const LinphoneFriend* lFriend, const std::string &filter, const std::string &withDomain); + std::list searchInFriend(const LinphoneFriend* lFriend, const std::string &filter, const std::string &withDomain); /** * Search informations in address given @@ -199,6 +200,8 @@ private: **/ bool checkDomain(const LinphoneFriend* lFriend, const LinphoneAddress *lAddress, const std::string &withDomain) const; + void addResultsToResultsList(std::list &results, std::list &srL); + L_DECLARE_PRIVATE(MagicSearch); }; diff --git a/src/search/search-result.cpp b/src/search/search-result.cpp index d8b78adea..c7494768a 100644 --- a/src/search/search-result.cpp +++ b/src/search/search-result.cpp @@ -42,6 +42,7 @@ SearchResult::SearchResult(const unsigned int weight, const LinphoneAddress *a, L_D(); d->mWeight = weight; d->mAddress = a; + if (d->mAddress) linphone_address_ref(const_cast(d->mAddress)); d->mFriend = f; d->mPhoneNumber = pn; } diff --git a/tester/group_chat_tester.c b/tester/group_chat_tester.c index b3f8b6bf0..f4f43d466 100644 --- a/tester/group_chat_tester.c +++ b/tester/group_chat_tester.c @@ -3144,7 +3144,7 @@ static void imdn_for_group_chat_room (void) { BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatReceivedChloeMessage), 2, int, "%d"); for (bctbx_list_t *item = participantsThatReceivedChloeMessage; item; item = bctbx_list_next(item)) { LinphoneParticipantImdnState *state = (LinphoneParticipantImdnState *)bctbx_list_get_data(item); - BC_ASSERT_GREATER(linphone_participant_imdn_state_get_state_change_time(state), initialTime, int, "%d"); + BC_ASSERT_GREATER((int)linphone_participant_imdn_state_get_state_change_time(state), (int)initialTime, int, "%d"); BC_ASSERT_EQUAL(linphone_participant_imdn_state_get_state(state), LinphoneChatMessageStateDeliveredToUser, int, "%d"); BC_ASSERT_PTR_NOT_NULL(linphone_participant_imdn_state_get_participant(state)); } diff --git a/tester/setup_tester.c b/tester/setup_tester.c index dfd74b6ec..abf5f3fe9 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -69,7 +69,8 @@ static void _check_friend_result_list(LinphoneCore *lc, const bctbx_list_t *resu const LinphoneSearchResult *sr = bctbx_list_nth_data(resultList, index); const LinphoneFriend *lf = linphone_search_result_get_friend(sr); if (lf) { - const LinphoneAddress *la = linphone_friend_get_address(lf); + const LinphoneAddress *la = (linphone_search_result_get_address(sr)) ? + linphone_search_result_get_address(sr) : linphone_friend_get_address(lf); if (la) { char* fa = linphone_address_as_string(la); BC_ASSERT_STRING_EQUAL(fa , uri); @@ -482,6 +483,91 @@ static void custom_tones_setup(void){ linphone_core_manager_destroy(mgr); } +static void search_friend_in_alphabetical_order(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + + const char *name1SipUri = {"sip:toto@sip.example.org"}; + const char *name2SipUri = {"sip:stephanie@sip.example.org"}; + const char *name3SipUri = {"sip:alber@sip.example.org"}; + const char *name4SipUri = {"sip:gauthier@sip.example.org"}; + + LinphoneFriend *friend1 = linphone_core_create_friend(manager->lc); + LinphoneFriend *friend2 = linphone_core_create_friend(manager->lc); + LinphoneFriend *friend3 = linphone_core_create_friend(manager->lc); + LinphoneFriend *friend4 = linphone_core_create_friend(manager->lc); + + LinphoneVcard *vcard1 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *vcard2 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *vcard3 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *vcard4 = linphone_factory_create_vcard(linphone_factory_get()); + + const char *name1 = {"STEPHANIE delarue"}; + const char *name2 = {"alias delarue"}; + const char *name3 = {"Alber josh"}; + const char *name4 = {"gauthier wei"}; + + linphone_vcard_set_full_name(vcard1, name1); // STEPHANIE delarue + linphone_vcard_set_url(vcard1, name1SipUri); //sip:toto@sip.example.org + linphone_vcard_add_sip_address(vcard1, name1SipUri); + linphone_friend_set_vcard(friend1, vcard1); + linphone_core_add_friend(manager->lc, friend1); + + linphone_vcard_set_full_name(vcard2, name2); // alias delarue + linphone_vcard_set_url(vcard2, name2SipUri); //sip:stephanie@sip.example.org + linphone_vcard_add_sip_address(vcard2, name2SipUri); + linphone_friend_set_vcard(friend2, vcard2); + linphone_core_add_friend(manager->lc, friend2); + + linphone_vcard_set_full_name(vcard3, name3); // Alber josh + linphone_vcard_set_url(vcard3, name3SipUri); //sip:alber@sip.example.org + linphone_vcard_add_sip_address(vcard3, name3SipUri); + linphone_friend_set_vcard(friend3, vcard3); + linphone_core_add_friend(manager->lc, friend3); + + linphone_vcard_set_full_name(vcard4, name4); // gauthier wei + linphone_vcard_set_url(vcard4, name4SipUri); //sip:gauthier@sip.example.org + linphone_vcard_add_sip_address(vcard4, name4SipUri); + linphone_friend_set_vcard(friend4, vcard4); + linphone_core_add_friend(manager->lc, friend4); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 4, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, name3SipUri, NULL);//"sip:stephanie@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, name2SipUri, NULL);//"sip:alber@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, name4SipUri, NULL);//"sip:gauthier@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 3, name1SipUri, NULL);//"sip:toto@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + linphone_friend_list_remove_friend(lfl, friend1); + linphone_friend_list_remove_friend(lfl, friend2); + linphone_friend_list_remove_friend(lfl, friend3); + linphone_friend_list_remove_friend(lfl, friend4); + + if (friend1) linphone_friend_unref(friend1); + if (friend2) linphone_friend_unref(friend2); + if (friend3) linphone_friend_unref(friend3); + if (friend4) linphone_friend_unref(friend4); + + if (vcard1) linphone_vcard_unref(vcard1); + if (vcard2) linphone_vcard_unref(vcard2); + if (vcard3) linphone_vcard_unref(vcard3); + if (vcard4) linphone_vcard_unref(vcard4); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); + +} + static void search_friend_without_filter(void) { LinphoneMagicSearch *magicSearch = NULL; bctbx_list_t *resultList = NULL; @@ -968,6 +1054,57 @@ static void search_friend_with_name_with_uppercase(void) { linphone_core_manager_destroy(manager); } +static void search_friend_with_multiple_sip_address(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *stephanieSipUri1 = {"sip:toto@sip.example.org"}; + const char *stephanieSipUri2 = {"sip:stephanie@sip.example.org"}; + LinphoneFriend *stephanieFriend = linphone_core_create_friend(manager->lc); + LinphoneVcard *stephanieVcard = linphone_factory_create_vcard(linphone_factory_get()); + const char *stephanieName = {"stephanie delarue"}; + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + linphone_vcard_set_full_name(stephanieVcard, stephanieName); // stephanie delarue + linphone_vcard_set_url(stephanieVcard, stephanieSipUri1); //sip:toto@sip.example.org + linphone_vcard_add_sip_address(stephanieVcard, stephanieSipUri1); + linphone_vcard_add_sip_address(stephanieVcard, stephanieSipUri2); + linphone_friend_set_vcard(stephanieFriend, stephanieVcard); + linphone_core_add_friend(manager->lc, stephanieFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "stephanie", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri2, NULL);//"sip:stephanie@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, stephanieSipUri1, NULL);//"sip:toto@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "delarue", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri2, NULL);//"sip:stephanie@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, stephanieSipUri1, NULL);//"sip:toto@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + linphone_friend_list_remove_friend(lfl, stephanieFriend); + if (stephanieFriend) linphone_friend_unref(stephanieFriend); + if (stephanieVcard) linphone_vcard_unref(stephanieVcard); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + static void search_friend_large_database(void) { char *dbPath = bc_tester_res("db/friends.db"); char *searchedFriend = "6295103032641994169"; @@ -1013,6 +1150,7 @@ test_t setup_tests[] = { TEST_NO_TAG("Codec usability", codec_usability_test), TEST_NO_TAG("Codec setup", codec_setup), TEST_NO_TAG("Custom tones setup", custom_tones_setup), + TEST_ONE_TAG("Return friend list in alphabetical order", search_friend_in_alphabetical_order, "MagicSearch"), TEST_ONE_TAG("Search friend without filter", search_friend_without_filter, "MagicSearch"), TEST_ONE_TAG("Search friend from all domains", search_friend_all_domains, "MagicSearch"), TEST_ONE_TAG("Search friend from one domain", search_friend_one_domain, "MagicSearch"), @@ -1024,6 +1162,7 @@ test_t setup_tests[] = { TEST_ONE_TAG("Search friend last item is the filter", search_friend_last_item_is_filter, "MagicSearch"), TEST_ONE_TAG("Search friend with name", search_friend_with_name, "MagicSearch"), TEST_ONE_TAG("Search friend with uppercase name", search_friend_with_name_with_uppercase, "MagicSearch"), + TEST_ONE_TAG("Search friend with multiple sip address", search_friend_with_multiple_sip_address, "MagicSearch"), TEST_ONE_TAG("Search friend in large friends database", search_friend_large_database, "MagicSearch") }; diff --git a/wrappers/cpp/CMakeLists.txt b/wrappers/cpp/CMakeLists.txt index 1042d749d..1e2e25a10 100644 --- a/wrappers/cpp/CMakeLists.txt +++ b/wrappers/cpp/CMakeLists.txt @@ -34,7 +34,6 @@ add_custom_command(OUTPUT include/linphone++/linphone.hh src/linphone++.cc enums_header.mustache main_header.mustache linphone-doc - "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml/index.xml" ) add_library(linphone++ SHARED diff --git a/wrappers/csharp/CMakeLists.txt b/wrappers/csharp/CMakeLists.txt index 0be827872..00c4b4cb0 100644 --- a/wrappers/csharp/CMakeLists.txt +++ b/wrappers/csharp/CMakeLists.txt @@ -28,7 +28,6 @@ add_custom_command(OUTPUT LinphoneWrapper.cs genwrapper.py wrapper_impl.mustache linphone-doc - "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml/index.xml" ) add_custom_target(linphonecs ALL DEPENDS LinphoneWrapper.cs) diff --git a/wrappers/java/CMakeLists.txt b/wrappers/java/CMakeLists.txt index 6f6cda660..a6fb895d2 100644 --- a/wrappers/java/CMakeLists.txt +++ b/wrappers/java/CMakeLists.txt @@ -20,10 +20,13 @@ # ############################################################################ -add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/src/linphone_jni.cc" +set(jni_sources "${CMAKE_CURRENT_BINARY_DIR}/src/linphone_jni.cc") + +add_custom_command(OUTPUT "${jni_sources}" COMMAND ${CMAKE_COMMAND} -E remove -f java/org/linphone/core/* src/* COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/genwrapper.py" "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml" "-o" "${CMAKE_CURRENT_BINARY_DIR}" DEPENDS ${PROJECT_SOURCE_DIR}/tools/genapixml.py ${LINPHONE_HEADER_FILES} + ${PROJECT_SOURCE_DIR}/tools/metaname.py ${PROJECT_SOURCE_DIR}/tools/metadoc.py ${PROJECT_SOURCE_DIR}/tools/abstractapi.py genwrapper.py @@ -33,13 +36,12 @@ add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/src/linphone_jni.cc" java_interface.mustache jni.mustache linphone-doc - "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml/index.xml" COMMENT "Generating java wrapper" ) -add_custom_target(linphonej ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/src/linphone_jni.cc") +add_custom_target(linphonej ALL DEPENDS "${jni_sources}") -set(LINPHONE_JNI_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/src/linphone_jni.cc" PARENT_SCOPE) +set(LINPHONE_JNI_SOURCES "${jni_sources}" PARENT_SCOPE) install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/java" DESTINATION "${CMAKE_INSTALL_DATADIR}/linphonej/") install(DIRECTORY classes/ DESTINATION "${CMAKE_INSTALL_DATADIR}/linphonej/java/org/linphone/core/")