Commit 853ef9ac authored by Julien Wadel's avatar Julien Wadel
Browse files

Fix doc wrapper on getting callback

- fix cast for x64

move linphone_magic_search_get_callbacks_list to wrapper-utils and mark it to not wrap

Add missing header

Fix Mac build by selecting LDAP from SDK first rather than system framework
parent 45f88c6e
......@@ -24,29 +24,47 @@
# OPENLDAP_INCLUDE_DIRS - the OpenLDAP include directory
# OPENLDAP_LIBRARIES - The libraries needed to use OpenLDAP
#Note : There are double find* because of priority given to the HINTS first. The second call will keep the result if there is one.
#INCLUDES
find_path(OPENLDAP_INCLUDE_DIRS
NAMES ldap.h
PATH_SUFFIXES include/openldap
HINTS "${CMAKE_INSTALL_PREFIX}"
NO_DEFAULT_PATH
)
find_path(OPENLDAP_INCLUDE_DIRS
NAMES ldap.h
PATH_SUFFIXES include/openldap
HINTS "${CMAKE_INSTALL_PREFIX}"
)
#LDAP
find_library(LDAP_LIB
NAMES ldap
HINTS "${CMAKE_INSTALL_PREFIX}"
PATH_SUFFIXES lib
NO_DEFAULT_PATH
)
find_library(LDAP_LIB
NAMES ldap
HINTS "${CMAKE_INSTALL_PREFIX}"
PATH_SUFFIXES lib
)
#LBER
find_library(LBER_LIB
NAMES lber
HINTS "${CMAKE_INSTALL_PREFIX}"
PATH_SUFFIXES lib
NO_DEFAULT_PATH
)
find_library(LBER_LIB
NAMES lber
HINTS "${CMAKE_INSTALL_PREFIX}"
PATH_SUFFIXES lib
)
if(WIN32)
find_library(LDAP_LIB
NAMES ldap
HINTS "${CMAKE_INSTALL_PREFIX}"
PATH_SUFFIXES lib
)
find_library(LBER_LIB
NAMES lber
HINTS "${CMAKE_INSTALL_PREFIX}"
PATH_SUFFIXES lib
)
set(OPENLDAP_LIBRARIES ${LDAP_LIB} ${LBER_LIB})
else()
find_library(OPENLDAP_LIBRARIES
NAMES ldap
HINTS "${CMAKE_INSTALL_PREFIX}"
PATH_SUFFIXES bin lib
)
endif()
set(OPENLDAP_LIBRARIES ${LDAP_LIB} ${LBER_LIB})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenLDAP
......
This diff is collapsed.
......@@ -68,13 +68,6 @@ LINPHONE_PUBLIC void linphone_magic_search_add_callbacks(LinphoneMagicSearch *ma
*/
LINPHONE_PUBLIC void linphone_magic_search_remove_callbacks(LinphoneMagicSearch *magic_search, LinphoneMagicSearchCbs *cbs);
/**
* Gets the list of listeners from a #LinphoneMagicSearch.maybenil
* @param magic_search #LinphoneMagicSearch object. @notnil
* @return The list of #LinphoneMagicSearchCbs object. @maybenil
*/
LINPHONE_PUBLIC const bctbx_list_t *linphone_magic_search_get_callbacks_list(const LinphoneMagicSearch *magic_search);
/**
* Gets the current LinphoneMagicSearchCbs.
* This is meant only to be called from a callback to be able to get the user_data associated with the #LinphoneMagicSearchCbs that is calling the callback.
......
......@@ -130,6 +130,14 @@ LINPHONE_PUBLIC void linphone_chat_room_allow_multipart(LinphoneChatRoom *room);
*/
LINPHONE_PUBLIC void linphone_chat_room_allow_cpim(LinphoneChatRoom *room);
/**
* Gets the list of listeners from a #LinphoneMagicSearch.
* @param magic_search #LinphoneMagicSearch object. @notnil
* @return The list of listeners that have been added. \bctbx_list{LinphoneMagicSearchCbs} @maybenil
* @donotwrap
*/
LINPHONE_PUBLIC const bctbx_list_t *linphone_magic_search_get_callbacks_list(const LinphoneMagicSearch *magic_search);
/************ */
/* DEPRECATED */
/* ********** */
......
......@@ -288,7 +288,8 @@ endif()
if(ENABLE_LDAP)
list(APPEND LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
ldap/ldap-friend.h
ldap/ldap-config-keys.h
ldap/ldap-contact-fields.h
ldap/ldap-contact-provider.h
ldap/ldap-contact-search.h
)
......@@ -458,7 +459,8 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES
)
if(ENABLE_LDAP)
list(APPEND LINPHONE_CXX_OBJECTS_SOURCE_FILES
ldap/ldap-friend.cpp
ldap/ldap-config-keys.cpp
ldap/ldap-contact-fields.cpp
ldap/ldap-contact-provider.cpp
ldap/ldap-contact-search.cpp
)
......
......@@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "linphone/wrapper_utils.h"
#include "c-wrapper/c-wrapper.h"
#include "search/magic-search.h"
......
/*
* Copyright (c) 2021 Belledonne Communications SARL.
*
* This file is part of Liblinphone.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ldap-config-keys.h"
#include <algorithm>
#include <fstream>
LINPHONE_BEGIN_NAMESPACE
static const std::map<std::string, LdapConfigKeys> gLdapConfigKeys={
{"timeout", LdapConfigKeys("5")},
{"max_results", LdapConfigKeys("5")},
{"auth_method", LdapConfigKeys("SIMPLE")},
{"password", LdapConfigKeys("")},
{"bind_dn", LdapConfigKeys("", TRUE)},
{"base_object", LdapConfigKeys("dc=example,dc=com", TRUE)},
{"server", LdapConfigKeys("ldap:///", TRUE)},
{"filter", LdapConfigKeys("(sn=*%s*)")},
{"name_attribute", LdapConfigKeys("sn")},
{"sip_attribute", LdapConfigKeys("mobile,telephoneNumber,homePhone,sn")},
{"sip_scheme", LdapConfigKeys("sip")},
{"sip_domain", LdapConfigKeys("sip.linphone.org")},
{"enable", LdapConfigKeys("1")},
{"use_sal", LdapConfigKeys("0")},
{"use_tls", LdapConfigKeys("1")},
{"debug", LdapConfigKeys("0")},
{"verify_server_certificates", LdapConfigKeys("-1")}// -1:auto from core, 0:deactivate, 1:activate
};
LdapConfigKeys::LdapConfigKeys(const std::string& pValue, const bool_t& pRequired) : value(pValue), required(pRequired){}
std::vector<std::string> LdapConfigKeys::split(const std::string& pValue){
std::vector<std::string> tokens;
std::istringstream iss(pValue);
std::string s;
while (std::getline(iss, s, ',')) {
tokens.push_back(s);
}
return tokens;
}
bool_t LdapConfigKeys::validConfig(const std::map<std::string, std::string>& config) {
bool_t valid = TRUE;
for(auto it = gLdapConfigKeys.begin() ; it != gLdapConfigKeys.end() ; ++it)
if( it->second.required && config.count(it->first)<=0){
ms_error("[LDAP] : Missing LDAP config value for '%s'", it->first.c_str());
valid = FALSE;
}
return valid;
}
std::map<std::string,std::string> LdapConfigKeys::loadConfig(const std::map<std::string, std::string>& config
, std::vector<std::string> * pNameAttributes
, std::vector<std::string> * pSipAttributes
, std::vector<std::string> * pAttributes
) {
std::map<std::string,std::string> finalConfig;
for(auto it = gLdapConfigKeys.begin() ; it != gLdapConfigKeys.end() ; ++it)
finalConfig[it->first] = (config.count(it->first)>0 ? config.at(it->first) : it->second.value);
*pNameAttributes = LdapConfigKeys::split(finalConfig["name_attribute"]);
*pSipAttributes = LdapConfigKeys::split(finalConfig["sip_attribute"]);
// Get first array and then keep only unique
*pAttributes = *pNameAttributes;
for(auto it = pSipAttributes->begin() ; it != pSipAttributes->end() ; ++it)
if( std::find(pAttributes->begin(), pAttributes->end(), *it) == pAttributes->end())
pAttributes->push_back(*it);
return finalConfig;
}
LINPHONE_END_NAMESPACE
/*
* Copyright (c) 21021 Belledonne Communications SARL.
*
* This file is part of Liblinphone.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LINPHONE_LDAP_CONFIG_KEYS_H
#define LINPHONE_LDAP_CONFIG_KEYS_H
#include "linphone/types.h"
#include <map>
#include <string>
#include <vector>
LINPHONE_BEGIN_NAMESPACE
class LdapConfigKeys{
public:
LdapConfigKeys(const std::string& pValue, const bool_t& pRequired=FALSE);
/**
* Manage Configurations.
* An instance store a configuration value in order to customize attributes.
*
* Available Keys : default.
* - "server" : "ldap:///", Required.
* LDAP Server. eg: ldap:/// for a localhost server or ldap://ldap.example.org/
* - "bind_dn" : "", Required.
* Bind DN to use for bindings. The bindDN DN is the credential that is used to authenticate against an LDAP.
* eg: cn=ausername,ou=people,dc=bc,dc=com
* - "base_object" : "dc=example,dc=com", Required.
* BaseObject is a specification for LDAP Search Scopes that specifies that the Search Request should only be performed against the entry specified as the search base DN.
* No entries below it will be considered.
* - "timeout" : "5".
* Timeout in seconds
* - "max_results" : "5".
* The max results when requesting searches.
* - "auth_method" : "SIMPLE".
* Authentification method. Only "SIMPLE" and "ANONYMOUS" are supported (Same simple mechanism)
* - "password" : "".
* Password to pass to server when binding.
* - "filter" : "(sn=*%s*)".
* The search is base on this filter to search friends.
* - "name_attribute" : "sn".
* Check these attributes To build Name Friend, separated by a comma and the first is the highest priority.
* - "sip_attribute" : "mobile,telephoneNumber,homePhone,sn".
* Check these attributes to build the SIP username in address of Friend. Attributes are separated by a comma and the first is the highest priority.
* - "sip_scheme" : "sip".
* Add the scheme to the sip address(scheme:username@domain).
* - "sip_domain" : "sip.linphone.org".
* Add the domain to the sip address(scheme:username@domain).
* - "enable" : "1".
* If this config is enabled.
* - "use_sal" : "0".
* The dns resolution is done by Linphone using Sal. It will pass an IP to LDAP. By doing that, the TLS negociation could not check the hostname.
* You may deactivate the verifications if wanted to force the connection.
* - "use_tls" : "1".
* Encrypt transactions by LDAP over TLS(StartTLS). You must use \'ldap\' scheme. \'ldaps\' for LDAP over SSL is non-standardized and deprecated.
* StartTLS in an extension to the LDAP protocol which uses the TLS protocol to encrypt communication.
* It works by establishing a normal - i.e. unsecured - connection with the LDAP server before a handshake negotiation between the server and the web services is carried out. Here, the server sends its certificate to prove its identity before the secure connection is established.
* - "debug" : "0".
* Debug mode
* - "verify_server_certificates" : "-1". values: -1:auto from core, 0:deactivate, 1:activate
* Specify whether the tls server certificate must be verified when connecting to a LDAP server.
**/
std::string value;
/**
* Specify if this value is required for the configuration.
**/
bool_t required;
/**
* Split a string into an array of token using ',' separator
* @param value The string to split
* @return An array of string
**/
static std::vector<std::string> split(const std::string& value);
/**
* Load a full configuration from an existant. The return value is the config with default value and a parsing is done to give attributes arrays.
* @param config The configuration <name,value>
* @param nameAttributes All values attributes from 'name_attribute' key
* @param sipAttributes All values attributes from 'sip_attribute' key
* @param attributes All unique attributes from keys'name_attribute' and 'sip_attribute' both
* @return The #LinphoneAccountCbs object. @notnil
**/
static bool_t validConfig(const std::map<std::string, std::string>& config);
/**
* Load a full configuration from an existant. The return value is the config with default value and a parsing is done to give attributes arrays.
* @param config The configuration <name,value>
* @param nameAttributes All values attributes from 'name_attribute' key
* @param sipAttributes All values attributes from 'sip_attribute' key
* @param attributes All unique attributes from keys'name_attribute' and 'sip_attribute' both
* @return The #LinphoneAccountCbs object. @notnil
**/
static std::map<std::string,std::string> loadConfig(const std::map<std::string, std::string>& config
, std::vector<std::string> * nameAttributes
, std::vector<std::string> * sipAttributes
, std::vector<std::string> * attributes);
};
LINPHONE_END_NAMESPACE
#endif /* LINPHONE_LDAP_CONFIG_KEYS_H */
......@@ -17,13 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ldap-friend.h"
#include "ldap-contact-fields.h"
LINPHONE_BEGIN_NAMESPACE
LDAPFriend::LDAPFriend(){
mSipIndex=-1;
mNameIndex=-1;
LdapContactFields::LdapContactFields(){
mSip.second = -1;
mName.second = -1;
}
LINPHONE_END_NAMESPACE
/*
* Copyright (c) 2010-2019 Belledonne Communications SARL.
* Copyright (c) 2021 Belledonne Communications SARL.
*
* This file is part of Liblinphone.
*
......@@ -17,23 +17,30 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LINPHONE_LDAP_FRIEND_H_
#define LINPHONE_LDAP_FRIEND_H_
#ifndef LINPHONE_LDAP_CONTACT_FIELDS_H_
#define LINPHONE_LDAP_CONTACT_FIELDS_H_
#include "linphone/types.h"
LINPHONE_BEGIN_NAMESPACE
class LDAPFriend {
class LdapContactFields {
public:
LDAPFriend();
// From a request, the index is the index that matches to the attribute vector. It is used for giving priority on attributes (eg: mobile and then telephoneNumber if first is not good enough to take account)
std::string mName;
int mNameIndex;
std::string mSip;
int mSipIndex;
LdapContactFields();
/**
* Regroup findings and keep the best choice.
*
* A pair is the string to use with its priority. If -1, then there is not defined result.
* It is used for giving priority on attributes (eg: mobile and then telephoneNumber if mobile is not good enough to take account)
*
*/
std::pair< std::string, int> mName;
std::pair< std::string, int> mSip;
};
LINPHONE_END_NAMESPACE
#endif /* LINPHONE_LDAP_FRIEND_H_ */
#endif /* LINPHONE_LDAP_CONTACT_FIELDS_H_ */
This diff is collapsed.
......@@ -35,70 +35,147 @@
LINPHONE_BEGIN_NAMESPACE
class LDAPContactSearch;
class LDAPFriend;
class LdapContactSearch;
class LdapContactFields;
class LINPHONE_PUBLIC LDAPContactProvider {
class LINPHONE_PUBLIC LdapContactProvider {
public:
/**
* Current action of the provider following this flow:
* ACTION_NONE => ACTION_INIT => (ACTION_WAIT_DNS) => ACTION_INITIALIZE => ACTION_BIND => ACTION_WAIT_BIND => ACTION_WAIT_REQUEST =>]
*/
enum{
STATE_ERROR = -1,
STATE_OK = 0,
STATE_CONNECTED
};
enum{
ACTION_NONE = 0,
ACTION_INIT,
ACTION_WAIT_DNS,
ACTION_INITIALIZE,
ACTION_BIND,
ACTION_WAIT_BIND,
ACTION_WAIT_REQUEST
ACTION_ERROR = -1, // Error State
ACTION_NONE = 0, // Do nothing
ACTION_INIT, // First step of initialization. Check domain and use Sal if requested.
ACTION_WAIT_DNS, // Sal is processing : wait till a result
ACTION_INITIALIZE, // Initialize the connection to the server
ACTION_BIND, // Bind to the server
ACTION_WAIT_BIND, // Wait for binding
ACTION_WAIT_REQUEST // Wait for processing search requests
};
// CREATION
LDAPContactProvider(const std::shared_ptr<Core> &core, const std::map<std::string,std::string> &config );
virtual ~LDAPContactProvider();
static std::vector<std::shared_ptr<LDAPContactProvider> > create(const std::shared_ptr<Core> &core);// Read configuration and create all providers from them
void initializeLdap(); // call ldap_initialize and set options. Return mState
/**
* @brief LdapContactProvider Instance to make searches on a LDAP server. Use create() to get all usable #LdapContactProvider.
* Only LDAP/STARTTLS is supported.
* @param core The Linphone core for Configurations, thread processing and callbacks
* @param config The configuration to used. It can contains only required fields, all others will be filled by default values. Check #LdapConfigKeys to know what fields are requiered
*/
LdapContactProvider(const std::shared_ptr<Core> &core, const std::map<std::string,std::string> &config );
virtual ~LdapContactProvider();
/**
* @brief create Create a list of #LdapContactProvider from the core's configuration : The section name is 'ldap' and have an additionnal index to separate servers (eg. 'ldap_4').
* A section must be enabled with 'enable' to 1 to be taken account.
* @param core The Linphone core
* @return A list of #LdapContactProvider
*/
static std::vector<std::shared_ptr<LdapContactProvider> > create(const std::shared_ptr<Core> &core);
/**
* @brief initializeLdap Call ldap_initialize, set options and start TLS if needed.
*/
void initializeLdap();
// CONFIGURATION
bool_t validConfig(const std::map<std::string, std::string>& dict)const;
void loadConfig(const std::map<std::string, std::string>& config);
/**
* @brief getTimeout it's a convertor from configuration 'timeout' to integer
* @return The timeout
*/
int getTimeout() const;
/**
* @brief getFilter Get filter key from Configuration
* @return The filter as astring
*/
std::string getFilter()const;
/**
* @brief getCurrentAction Get the current action of Iteration.
* @return Return ACTION_ERROR in case of error.
*/
int getCurrentAction()const;
// SEARCH
/**
* @brief search Make a search to the provider. Results are retrieved from the callback #ContactSearchCallback.
* This function is thread-safe.
* @param mPredicate A value to be used to replace a format specifier in the format string : 'filter' configuration key.
* This key is a string that contains a format string that follows the same specifications as format in printf.
* @param mCb The callback where to get results in the form of 'static void resultsCb( LinphoneContactSearch* id, bctbx_list_t* friends, void* data );'
* @param mCbData The data to pass to the callback
*/
void search(const std::string& mPredicate, ContactSearchCallback mCb, void* mCbData);
int search(std::shared_ptr<LDAPContactSearch> request);
std::list<std::shared_ptr<LDAPContactSearch> >::iterator cancelSearch(LDAPContactSearch* req);
LDAPContactSearch* requestSearch( int msgid );
int completeContact( LDAPFriend* lf, const char* attr_name, const char* attr_value);
/**
* @brief search Start the search to LDAP
* @param request Request instance that contains data to make a search.
* @return the result of ldap_search_ext (LDAP_SUCCESS on success)
*/
int search(std::shared_ptr<LdapContactSearch> request);
/**
* @brief cancelSearch Remove the search from the list and call the callback
* @param request the request
* @return The new list iterator after the deletion of the request
*/
std::list<std::shared_ptr<LdapContactSearch> >::iterator cancelSearch(LdapContactSearch* request);
/**
* @brief requestSearch Get the #LdapContactSearch linked to the ID
* @param msgid The ID of the search request
* @return The #LdapContactSearch linked to the ID. NULL if no request has been found.
*/
LdapContactSearch* requestSearch( int msgid );
/**
* @brief completeContact Fill LdapContactFields with the attribute. This function has to be call for each attributes.
* The function use 'sip_scheme' and 'sip_domain' to complete the SIP attribute (scheme:attr_value@domain). These options can be empty to avoid this behaviour.
* @param lf the contact to fill
* @param attr_name The attribute name from LDAP.
* @param attr_value The value from LDAP.
* @return 1 if all contact's fields are filled. 0 if some fields are missing.
*/
int completeContact( LdapContactFields* lf, const char* attr_name, const char* attr_value);
// ASYNC PROCESSING
/**
* @brief iterate This function is called from main loop to do actions that need to be serialized.
* @param data A pointer to #LdapContactProvider
* @return
*/
static bool_t iterate(void *data);
//static void* bind( void*arg);
//int bindAsync();// Start a thread to bind
void handleSearchResult( LDAPMessage* message );
/**
* @brief stun_server_resolved Callback for DNS resolution with Sal. It retrieve the Sal's result and replace the server domain to the IP.
* @param data #LdapContactProvider
* @param results The address from Sal
*/
static void stun_server_resolved(void *data, belle_sip_resolver_results_t *results);
private:
/**
* @brief handleSearchResult Parse the LDAPMessage to get contacts and fill Search entries.
* @param message LDAPMessage to parse
*/
void handleSearchResult( LDAPMessage* message );
std::shared_ptr<Core> mCore;
std::map<std::string,std::string> mConfig;
std::vector<std::string> mAttributes;
std::vector<std::string> mAttributes; // Request optimization to limit attributes
std::vector<std::string> mNameAttributes;// Optimization to avoid split each times
std::vector<std::string> mSipAttributes;// Optimization to avoid split each times
LDAP* mLd;
LDAP *mLd;
ortp_mutex_t mLock;
std::list<std::shared_ptr<LDAPContactSearch> > mRequests;
std::list<std::shared_ptr<LdapContactSearch> > mRequests;
// bind transaction
bool_t mConnected;
std::string mName;
int mAwaitingMessageId; // Waiting Message for ldap_abandon_ext on bind
bool_t mConnected; // If we are connected to server (bind)
int mCurrentAction; // Iteration action
belle_sip_resolver_context_t * mSalContext; // Sal Context for DNS
belle_generic_uri_t *mServerUri;//Used to optimized query on SAL
belle_sip_resolver_context_t * mSalContext;
std::string mServerUrl;
int mState;
int mCurrentAction;
int mAwaitingMessageId;
std::string mServerUrl; // URL to use for connection. It can be different from configuration
};
LINPHONE_END_NAMESPACE
......
......@@ -26,13 +26,13 @@
LINPHONE_BEGIN_NAMESPACE
LDAPContactSearch::LDAPContactSearch(const int& msgId){
LdapContactSearch::LdapContactSearch(const int& msgId){
mMsgId = msgId;
mFoundCount = 0;
mFoundEntries = NULL;
complete = 0;
}
LDAPContactSearch::LDAPContactSearch(LDAPContactProvider * parent, const std::string& predicate, ContactSearchCallback cb, void* cbData){
LdapContactSearch::LdapContactSearch(LdapContactProvider * parent, const std::string& predicate, ContactSearchCallback cb, void* cbData){
mPredicate = predicate;
mCb = cb;
mCbData = cbData;
......@@ -41,7 +41,7 @@ LDAPContactSearch::LDAPContactSearch(LDAPContactProvider * parent, const std::st
mFoundEntries = NULL;
complete = 0;