Commit f76c0ead authored by Sylvain Berfini's avatar Sylvain Berfini

Improved remote provisioning code + added test suite for it

parent 33df2c8f
......@@ -1265,7 +1265,7 @@ static void linphone_core_start(LinphoneCore * lc) {
linphone_core_set_state(lc,LinphoneGlobalOn,"Ready");
}
static void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message) {
void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message) {
if (lc->vtable.configuring_status)
lc->vtable.configuring_status(lc, state, message);
......@@ -1274,6 +1274,7 @@ static void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfigurin
static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata)
{
const char *remote_provisioning_uri = NULL;
ms_message("Initializing LinphoneCore %s", linphone_core_get_version());
memset (lc, 0, sizeof (LinphoneCore));
lc->config=config;
......@@ -1358,15 +1359,21 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
lc->network_last_check = 0;
lc->network_last_status = FALSE;
lc->http_provider = belle_sip_stack_create_http_provider(sal_get_belle_sip_stack(lc->sal), "0.0.0.0");
certificates_config_read(lc);
belle_tls_verify_policy_t *tls_policy = belle_tls_verify_policy_new();
belle_tls_verify_policy_set_root_ca(tls_policy, sal_get_root_ca(lc->sal));
belle_http_provider_set_tls_verify_policy(lc->http_provider, tls_policy);
if (lc->vtable.display_status)
lc->vtable.display_status(lc, _("Configuring"));
linphone_core_set_state(lc, LinphoneGlobalConfiguring, "Configuring");
const char *remote_provisioning_uri = lp_config_get_string(lc->config, "app", "remote_provisioning", NULL);
remote_provisioning_uri = lp_config_get_string(lc->config, "app", "remote_provisioning", NULL);
if (remote_provisioning_uri) {
certificates_config_read(lc);
linphone_remote_provisioning_download_and_apply(lc, remote_provisioning_uri, linphone_configuring_terminated);
linphone_remote_provisioning_download_and_apply(lc, remote_provisioning_uri);
} else {
linphone_configuring_terminated(lc, LinphoneConfiguringSkipped, NULL);
}
......@@ -5470,6 +5477,9 @@ void net_config_uninit(LinphoneCore *lc)
{
net_config_t *config=&lc->net_conf;
if (lc->http_provider) {
belle_sip_object_unref(lc->http_provider);
}
if (config->stun_server!=NULL){
ms_free(config->stun_server);
}
......
......@@ -2303,16 +2303,6 @@ LINPHONE_PUBLIC void linphone_core_set_provisioning_uri(LinphoneCore *lc, const
**/
LINPHONE_PUBLIC const char* linphone_core_get_provisioning_uri(const LinphoneCore *lc);
typedef void (*ConfiguringCallback)(LinphoneCore *lc, LinphoneConfiguringState state, const char *message);
/**
* Download a remote provisioning file from the given uri and applies it to current lp config.
* A restart is requiered for the changes to be applied.
* @param lc the LinphoneCore
* @param remote_provisioning_uri the URI at which the remote provisioning file is available
*/
LINPHONE_PUBLIC void linphone_remote_provisioning_download_and_apply(LinphoneCore *lc, const char *remote_provisioning_uri, ConfiguringCallback cb);
#ifdef __cplusplus
}
#endif
......
......@@ -673,6 +673,7 @@ struct _LinphoneCore
#ifdef BUILD_UPNP
UpnpContext *upnp;
#endif //BUILD_UPNP
belle_http_provider_t *http_provider;
};
......@@ -806,6 +807,14 @@ const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, cons
void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc);
/*****************************************************************************
* REMOTE PROVISIONING FUNCTIONS *
****************************************************************************/
void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message);
void linphone_remote_provisioning_download_and_apply(LinphoneCore *lc, const char *remote_provisioning_uri);
/*****************************************************************************
* XML UTILITY FUNCTIONS *
****************************************************************************/
......
......@@ -21,9 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define XML2LPC_CALLBACK_BUFFER_SIZE 1024
static ConfiguringCallback linphone_callback = NULL;
static bool_t waiting_response = FALSE;
static void xml2lpc_callback(void *ctx, xml2lpc_log_level level, const char *fmt, va_list list) {
char buffer[XML2LPC_CALLBACK_BUFFER_SIZE];
vsnprintf(buffer, XML2LPC_CALLBACK_BUFFER_SIZE, fmt, list);
......@@ -44,22 +41,18 @@ static void linphone_remote_provisioning_apply(LinphoneCore *lc, const char *xml
if (result == 0) {
lp_config_sync(linphone_core_get_config(lc));
xml2lpc_context_destroy(context);
if (linphone_callback)
linphone_callback(lc, LinphoneConfiguringSuccessful, NULL);
linphone_configuring_terminated(lc, LinphoneConfiguringSuccessful, NULL);
} else {
xml2lpc_context_destroy(context);
if (linphone_callback)
linphone_callback(lc, LinphoneConfiguringFailed, "convert failed");
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "xml to lpc failed");
}
} else {
xml2lpc_context_destroy(context);
if (linphone_callback)
linphone_callback(lc, LinphoneConfiguringFailed, "set xml string failed");
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "invalid xml");
}
}
static void belle_request_process_response_event(void *ctx, const belle_http_response_event_t *event) {
waiting_response = FALSE;
LinphoneCore *lc = (LinphoneCore *)ctx;
belle_sip_message_t *body = BELLE_SIP_MESSAGE(event->response);
const char *message = belle_sip_message_get_body(body);
......@@ -67,75 +60,41 @@ static void belle_request_process_response_event(void *ctx, const belle_http_res
if (belle_http_response_get_status_code(event->response) == 200) {
linphone_remote_provisioning_apply(lc, message);
} else {
if (linphone_callback)
linphone_callback(lc, LinphoneConfiguringFailed, message);
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "http error");
}
}
static void belle_request_process_io_error(void *ctx, const belle_sip_io_error_event_t *event) {
waiting_response = FALSE;
LinphoneCore *lc = (LinphoneCore *)ctx;
if (linphone_callback)
linphone_callback(lc, LinphoneConfiguringFailed, "io error");
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "http io error");
}
static void belle_request_process_timeout(void *ctx, const belle_sip_timeout_event_t *event) {
waiting_response = FALSE;
LinphoneCore *lc = (LinphoneCore *)ctx;
if (linphone_callback)
linphone_callback(lc, LinphoneConfiguringFailed, "timeout");
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "http timeout");
}
static void belle_request_process_auth_requested(void *ctx, belle_sip_auth_event_t *event) {
waiting_response = FALSE;
LinphoneCore *lc = (LinphoneCore *)ctx;
if (linphone_callback)
linphone_callback(lc, LinphoneConfiguringFailed, "auth requested");
linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "http auth requested");
}
static belle_http_request_listener_callbacks_t belle_request_listener = {
belle_request_process_response_event,
belle_request_process_io_error,
belle_request_process_timeout,
belle_request_process_auth_requested
};
void linphone_remote_provisioning_download_and_apply(LinphoneCore *lc, const char *remote_provisioning_uri) {
belle_http_request_listener_callbacks_t belle_request_listener = {
belle_request_process_response_event,
belle_request_process_io_error,
belle_request_process_timeout,
belle_request_process_auth_requested
};
static void linphone_remote_provisioning_download(LinphoneCore *lc, const char *remote_provisioning_uri) {
belle_sip_object_pool_t *pool = belle_sip_object_pool_push();
belle_sip_stack_t *stack = belle_sip_stack_new(NULL);
belle_http_request_listener_t *listener = belle_http_request_listener_create_from_callbacks(&belle_request_listener, lc);
belle_http_provider_t *provider = belle_sip_stack_create_http_provider(stack, "0.0.0.0");
belle_http_request_t *request = belle_http_request_create(
"GET",
belle_generic_uri_parse(remote_provisioning_uri),
NULL
);
belle_http_provider_send_request(provider, request, listener);
waiting_response = TRUE;
while (waiting_response) {
belle_sip_stack_sleep(stack, 10);
}
belle_sip_object_unref(pool);
belle_sip_object_unref(provider);
belle_sip_object_unref(stack);
}
/**
* Fetches the remote provisioning from the given URI and tries to apply it to the current LpConfig
* @param lc the LinphoneCore
* @param remote_provisioning_uri the URI at which the provisioning is available
*/
void linphone_remote_provisioning_download_and_apply(LinphoneCore *lc, const char *remote_provisioning_uri, ConfiguringCallback cb) {
linphone_callback = cb;
linphone_remote_provisioning_download(lc, remote_provisioning_uri);
belle_http_provider_send_request(lc->http_provider, request, listener);
}
void linphone_core_set_provisioning_uri(LinphoneCore *lc, const char*uri){
......
......@@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "config.h"
#endif
#include "sal/sal.h"
#include "bellesip_sal/sal_impl.h"
#include <ctype.h>
......@@ -626,5 +627,7 @@ int sal_body_has_type(const SalBody *body, const char *type, const char *subtype
&& strcmp(body->subtype,subtype)==0;
}
belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal) {
return sal->stack;
}
......@@ -697,4 +697,6 @@ int sal_body_has_type(const SalBody *body, const char *type, const char *subtype
/*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/
int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size);
belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal);
#endif
EXTRA_DIST= empty_rc laure_rc marie_early_rc marie_no_sdp_rc marie_rc multi_account_lrc pauline_alt_rc \
marie_remote_rc pauline_remote_rc marie_remote_404_rc marie_remote_invalid_rc \
pauline_rc pauline_wild_rc pauline_rc_tcp tester_hosts sounds images certificates
......@@ -15,7 +16,8 @@ liblinphone_tester_SOURCES= liblinphone_tester.c liblinphone_tester.h\
upnp_tester.c \
eventapi_tester.c \
flexisip_tester.c \
stun_tester.c
stun_tester.c \
remote_provisioning_tester.c
#liblinphone_tester_CFLAGS=$(CUNIT_CFLAGS)
......
......@@ -25,7 +25,7 @@
#include "CUnit/CUCurses.h"
#endif
static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file);
static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file, void* user_data);
static test_suite_t **test_suite = NULL;
static int nb_test_suites = 0;
......@@ -90,7 +90,7 @@ void reset_counters( stats* counters) {
memset(counters,0,sizeof(stats));
}
static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file) {
static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file, void* user_data) {
LinphoneCore* lc;
char filepath[256]={0};
char ringpath[256]={0};
......@@ -106,7 +106,7 @@ static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char*
CU_ASSERT_TRUE_FATAL(ortp_file_exist(filepath)==0);
}
lc = linphone_core_new(v_table,NULL,*filepath!='\0' ? filepath : NULL,NULL);
lc = linphone_core_new(v_table,NULL,*filepath!='\0' ? filepath : NULL, user_data);
sal_enable_test_features(lc->sal,TRUE);
snprintf(rootcapath, sizeof(rootcapath), "%s/certificates/cn/cafile.pem", path);
......@@ -200,9 +200,10 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f
mgr->v_table.subscription_state_changed=linphone_subscription_state_change;
mgr->v_table.notify_received=linphone_notify_received;
mgr->v_table.publish_state_changed=linphone_publish_state_changed;
mgr->lc=configure_lc_from(&mgr->v_table, liblinphone_tester_file_prefix, rc_file);
linphone_core_set_user_data(mgr->lc,mgr);
mgr->v_table.configuring_status=linphone_configuration_status;
reset_counters(&mgr->stat);
mgr->lc=configure_lc_from(&mgr->v_table, liblinphone_tester_file_prefix, rc_file, mgr);
/*CU_ASSERT_EQUAL(ms_list_size(linphone_core_get_proxy_config_list(lc)),proxy_count);*/
if (check_for_proxies && rc_file) /**/
proxy_count=ms_list_size(linphone_core_get_proxy_config_list(mgr->lc));
......@@ -328,6 +329,7 @@ void liblinphone_tester_init(void) {
add_test_suite(&stun_test_suite);
add_test_suite(&event_test_suite);
add_test_suite(&flexisip_test_suite);
add_test_suite(&remote_provisioning_test_suite);
}
void liblinphone_tester_uninit(void) {
......
......@@ -55,6 +55,7 @@ extern test_suite_t upnp_test_suite;
extern test_suite_t event_test_suite;
extern test_suite_t flexisip_test_suite;
extern test_suite_t stun_test_suite;
extern test_suite_t remote_provisioning_test_suite;
extern int liblinphone_tester_nb_test_suites(void);
......@@ -173,6 +174,10 @@ typedef struct _stats {
int number_of_LinphonePublishExpiring;
int number_of_LinphonePublishError;
int number_of_LinphonePublishCleared;
int number_of_LinphoneConfiguringSkipped;
int number_of_LinphoneConfiguringFailed;
int number_of_LinphoneConfiguringSuccessful;
}stats;
typedef struct _LinphoneCoreManager {
......@@ -203,6 +208,7 @@ void new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char
void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *ev, LinphoneSubscriptionState state);
void linphone_publish_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state);
void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content);
void linphone_configuration_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message);
LinphoneAddress * create_linphone_address(const char * domain);
bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value);
......
[app]
remote_provisioning=http://smtp.linphone.org/marie_404
[app]
remote_provisioning=http://smtp.linphone.org/marie_invalid
[app]
remote_provisioning=http://smtp.linphone.org/marie_xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">
<section name="sip">
<entry name="sip_port">-1</entry>
<entry name="sip_tcp_port">-1</entry>
<entry name="sip_tls_port">-1</entry>
<entry name="default_proxy">0</entry>
<entry name="ping_with_options">0</entry>
<entry name="register_only_when_network_is_up">0</entry>
<entry name="composing_idle_timeout">1</entry>
</section>
<section name="auth_info_0">
<entry name="username">marie</entry>
<entry name="userid">marie</entry>
<entry name="passwd">secret</entry>
<entry name="realm">sip.example.org</entry>
</section>
<section name="proxy_0">
<entry name="reg_proxy">sip.example.org;transport=tcp</entry>
<entry name="reg_route">sip.example.org;transport=tcp;lr</entry>
<entry name="reg_identity">sip:marie@sip.example.org</entry>
<entry name="reg_expires">3600</entry>
<entry name="reg_sendregister">1</entry>
<entry name="publish">0</entry>
<entry name="dial_escape_plus">0</entry>
</section>
<section name="friend_0">
<entry name="url">"Paupoche" &lt;sip:pauline@sip.example.org&gt;</entry>
<entry name="pol">accept</entry>
<entry name="subscribe">0</entry>
</section>
<section name="rtp">
<entry name="audio_rtp_port">8070</entry>
<entry name="video_rtp_port">9072</entry>
</section>
<section name="video">
<entry name="display">0</entry>
<entry name="capture">0</entry>
<entry name="show_local">0</entry>
<entry name="size">vga</entry>
<entry name="enabled">0</entry>
<entry name="self_view">0</entry>
<entry name="automatically_initiate">0</entry>
<entry name="automatically_accept">0</entry>
<entry name="device">StaticImage: Static picture</entry>
</section>
<section name="sound">
<entry name="echocancellation">0 #to not overload cpu in case of VG</entry>
</section>
</config>
[app]
remote_provisioning=https://smtp.linphone.org/pauline_xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">
<section name="sip">
<entry name="sip_port">-1</entry>
<entry name="sip_tcp_port">-1</entry>
<entry name="sip_tls_port">-1</entry>
<entry name="default_proxy">0</entry>
<entry name="ping_with_options">0</entry>
<entry name="register_only_when_network_is_up">0</entry>
<entry name="composing_idle_timeout">1</entry>
</section>
<section name="auth_info_0">
<entry name="username">pauline</entry>
<entry name="userid">pauline</entry>
<entry name="passwd">secret</entry>
<entry name="realm">sip.example.org</entry>
</section>
<section name="proxy_0">
<entry name="reg_proxy">sip2.linphone.org;transport=tls</entry>
<entry name="reg_route">sip2.linphone.org;transport=tls</entry>
<entry name="reg_identity">sip:pauline@sip.example.org</entry>
<entry name="reg_expires">3600</entry>
<entry name="reg_sendregister">1</entry>
<entry name="publish">0</entry>
<entry name="dial_escape_plus">0</entry>
</section>
<section name="rtp">
<entry name="audio_rtp_port">8090</entry>
<entry name="video_rtp_port">9092</entry>
</section>
<section name="video">
<entry name="display">0</entry>
<entry name="capture">0</entry>
<entry name="show_local">0</entry>
<entry name="size">vga</entry>
<entry name="enabled">0</entry>
<entry name="self_view">0</entry>
<entry name="automatically_initiate">0</entry>
<entry name="automatically_accept">0</entry>
<entry name="device">StaticImage: Static picture</entry>
</section>
<section name="sound">
<entry name="echocancellation">0 #to not overload cpu in case of VG</entry>
</section>
</config>
/*
liblinphone_tester - liblinphone test suite
Copyright (C) 2013 Belledonne Communications SARL
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 2 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 <stdio.h>
#include "CUnit/Basic.h"
#include "linphonecore.h"
#include "private.h"
#include "liblinphone_tester.h"
void linphone_configuration_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) {
stats* counters = get_stats(lc);
if (status == LinphoneConfiguringSkipped) {
counters->number_of_LinphoneConfiguringSkipped++;
} else if (status == LinphoneConfiguringFailed) {
counters->number_of_LinphoneConfiguringFailed++;
} else if (status == LinphoneConfiguringSuccessful) {
counters->number_of_LinphoneConfiguringSuccessful++;
}
}
static void remote_provisioning_skipped(void) {
LinphoneCoreManager* marie = linphone_core_manager_new2("marie_rc", FALSE);
CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringSkipped,1));
linphone_core_manager_destroy(marie);
}
static void remote_provisioning_http(void) {
LinphoneCoreManager* marie = linphone_core_manager_new("marie_remote_rc");
CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringSuccessful,1));
linphone_core_manager_destroy(marie);
}
static void remote_provisioning_https(void) {
LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_remote_rc");
CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneConfiguringSuccessful,1));
linphone_core_manager_destroy(pauline);
}
static void remote_provisioning_not_found(void) {
LinphoneCoreManager* marie = linphone_core_manager_new("marie_remote_404_rc");
CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringFailed,1));
linphone_core_manager_destroy(marie);
}
static void remote_provisioning_invalid(void) {
LinphoneCoreManager* marie = linphone_core_manager_new("marie_remote_invalid_rc");
CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringFailed,1));
linphone_core_manager_destroy(marie);
}
test_t remote_provisioning_tests[] = {
{ "Remote provisioning skipped", remote_provisioning_skipped },
{ "Remote provisioning successful behind http", remote_provisioning_http },
{ "Remote provisioning successful behind https", remote_provisioning_https },
{ "Remote provisioning 404 not found", remote_provisioning_not_found },
{ "Remote provisioning invalid", remote_provisioning_invalid }
};
test_suite_t remote_provisioning_test_suite = {
"RemoteProvisioning",
NULL,
NULL,
sizeof(remote_provisioning_tests) / sizeof(remote_provisioning_tests[0]),
remote_provisioning_tests
};
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment