diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 2771b1fec..96a59b838 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -542,8 +542,8 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){ ctx->callbacks.notify=(SalOnNotify)unimplemented_stub; if (ctx->callbacks.subscribe_received==NULL) ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub; - if (ctx->callbacks.subscribe_closed==NULL) - ctx->callbacks.subscribe_closed=(SalOnSubscribeClosed)unimplemented_stub; + if (ctx->callbacks.incoming_subscribe_closed==NULL) + ctx->callbacks.incoming_subscribe_closed=(SalOnIncomingSubscribeClosed)unimplemented_stub; if (ctx->callbacks.parse_presence_requested==NULL) ctx->callbacks.parse_presence_requested=(SalOnParsePresenceRequested)unimplemented_stub; if (ctx->callbacks.convert_presence_to_xml_requested==NULL) diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c index 802e5d334..75f87a2d9 100644 --- a/coreapi/bellesip_sal/sal_op_events.c +++ b/coreapi/bellesip_sal/sal_op_events.c @@ -46,11 +46,15 @@ static void subscribe_refresher_listener (belle_sip_refresher_t* refresher if (status_code==200) sss=SalSubscribeActive; else if (status_code==202) sss=SalSubscribePending; set_or_update_dialog(op,belle_sip_transaction_get_dialog(tr)); - } - if (status_code>=200){ - sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL); op->base.root->callbacks.subscribe_response(op,sss); - }else if (status_code==0){ + } else if (status_code >= 300) { + SalReason reason = SalReasonUnknown; + if (status_code == 503) { /*refresher returns 503 for IO error*/ + reason = SalReasonIOError; + } + sal_error_info_set(&op->error_info,reason,status_code,reason_phrase,NULL); + op->base.root->callbacks.subscribe_response(op,sss); + }if (status_code==0){ op->base.root->callbacks.on_expire(op); } @@ -172,7 +176,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque ms_message("Unsubscribe received from [%s]",sal_op_get_from(op)); resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); - op->base.root->callbacks.subscribe_closed(op); + op->base.root->callbacks.incoming_subscribe_closed(op); } } break; diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 345501b84..88d6cf0f9 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -518,14 +518,14 @@ SalReason _sal_reason_from_sip_code(int code) { return SalReasonNotImplemented; case 502: return SalReasonBadGateway; + case 503: + return SalReasonServiceUnavailable; case 504: return SalReasonServerTimeout; case 600: return SalReasonDoNotDisturb; case 603: return SalReasonDeclined; - case 503: - return SalReasonServiceUnavailable; default: return SalReasonUnknown; } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 6811d4c08..10921078e 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -1343,7 +1343,7 @@ static void subscribe_received(SalOp *op, const char *eventname, const SalBodyHa } -static void subscribe_closed(SalOp *op){ +static void incoming_subscribe_closed(SalOp *op){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); linphone_event_set_state(lev,LinphoneSubscriptionTerminated); @@ -1400,7 +1400,7 @@ SalCallbacks linphone_sal_callbacks={ is_composing_received, notify_refer, subscribe_received, - subscribe_closed, + incoming_subscribe_closed, subscribe_response, notify, subscribe_presence_received, diff --git a/coreapi/event.c b/coreapi/event.c index 7505fd723..2d6c8f270 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -35,7 +35,7 @@ const char *linphone_subscription_state_to_string(LinphoneSubscriptionState stat switch(state){ case LinphoneSubscriptionNone: return "LinphoneSubscriptionNone"; case LinphoneSubscriptionIncomingReceived: return "LinphoneSubscriptionIncomingReceived"; - case LinphoneSubscriptionOutgoingInit: return "LinphoneSubscriptionOutoingInit"; + case LinphoneSubscriptionOutgoingProgress: return "LinphoneSubscriptionOutgoingProgress"; case LinphoneSubscriptionPending: return "LinphoneSubscriptionPending"; case LinphoneSubscriptionActive: return "LinphoneSubscriptionActive"; case LinphoneSubscriptionTerminated: return "LinphoneSubscriptionTerminated"; diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 22b9fc0e8..9201d6d9c 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -419,6 +419,7 @@ void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, Linphon linphone_content_set_string_buffer(content, xml_content); linphone_event_send_subscribe(list->event, content); linphone_content_unref(content); + linphone_event_set_user_data(list->event, list); } } if (address != NULL) linphone_address_unref(address); @@ -476,3 +477,21 @@ void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, Lin linphone_content_unref(first_part); } } +void linphone_friend_list_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { + LinphoneFriendList *list = (LinphoneFriendList *)linphone_event_get_user_data(lev); + if (!list) { + ms_warning("core [%p] Receiving unexpected state [%s] for event [%p], no associated friend list",lc + , linphone_subscription_state_to_string(state) + , lev); + } else { + ms_message("Receiving new state [%s] for event [%p] for friend list [%p]" + , linphone_subscription_state_to_string(state) + , lev + , list); + + if (state == LinphoneSubscriptionOutgoingProgress) { + ms_message("Resseting version count for friend list [%p]",list); + list->expected_notification_version = 0; + } + } +} diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index dde230a29..e0dd9e24b 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1657,6 +1657,12 @@ static void linphone_core_internal_notify_received(LinphoneCore *lc, LinphoneEve } } +static void linphone_core_internal_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { + if (strcasecmp(linphone_event_get_name(lev), "Presence") == 0) { + linphone_friend_list_subscription_state_changed(lc, lev, state); + } +} + static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata){ const char *remote_provisioning_uri = NULL; LinphoneCoreVTable* local_vtable= linphone_core_v_table_new(); @@ -1671,6 +1677,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab linphone_task_list_init(&lc->hooks); internal_vtable->notify_received = linphone_core_internal_notify_received; + internal_vtable->subscription_state_changed = linphone_core_internal_subscription_state_changed; _linphone_core_add_listener(lc, internal_vtable, TRUE, TRUE); memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable)); _linphone_core_add_listener(lc, local_vtable, TRUE, FALSE); diff --git a/coreapi/private.h b/coreapi/private.h index 56ea85a41..8cb2d030a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -406,6 +406,7 @@ const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphonePro void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list); void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, LinphoneEvent *lev, const LinphoneContent *body); +void linphone_friend_list_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state); void _linphone_friend_list_release(LinphoneFriendList *list); void linphone_friend_invalidate_subscription(LinphoneFriend *lf); void linphone_friend_close_subscriptions(LinphoneFriend *lf); diff --git a/coreapi/vtables.c b/coreapi/vtables.c index ae523925d..a8840b5eb 100644 --- a/coreapi/vtables.c +++ b/coreapi/vtables.c @@ -245,7 +245,7 @@ void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, } void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { - NOTIFY_IF_EXIST(subscription_state_changed, lc,lev,state); + NOTIFY_IF_EXIST_INTERNAL(subscription_state_changed,linphone_event_is_internal(lev), lc,lev,state); cleanup_dead_vtable_refs(lc); } diff --git a/include/sal/sal.h b/include/sal/sal.h index b4078964d..acfc5d3b5 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -489,7 +489,7 @@ typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state); typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status); typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, SalBodyHandler *body); typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBodyHandler *body); -typedef void (*SalOnSubscribeClosed)(SalOp *salop); +typedef void (*SalOnIncomingSubscribeClosed)(SalOp *salop); typedef void (*SalOnParsePresenceRequested)(SalOp *salop, const char *content_type, const char *content_subtype, const char *content, SalPresenceModel **result); typedef void (*SalOnConvertPresenceToXMLRequested)(SalOp *salop, SalPresenceModel *presence, const char *contact, char **content); typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model, const char *msg); @@ -523,7 +523,7 @@ typedef struct SalCallbacks{ SalOnIsComposingReceived is_composing_received; SalOnNotifyRefer notify_refer; SalOnSubscribeReceived subscribe_received; - SalOnSubscribeClosed subscribe_closed; + SalOnIncomingSubscribeClosed incoming_subscribe_closed; SalOnSubscribeResponse subscribe_response; SalOnNotify notify; SalOnSubscribePresenceReceived subscribe_presence_received; diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index a8ada9ba2..ce7c60c31 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -24,7 +24,6 @@ #include #include "liblinphone_tester.h" - static const char *subscribe_content="blabla"; static const char *notify_content="blabla"; @@ -38,8 +37,9 @@ const char *liblinphone_tester_get_notify_content(void){ void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content){ LinphoneCoreManager *mgr; + const char * ua = linphone_event_get_custom_header(lev, "User-Agent"); BC_ASSERT_PTR_NOT_NULL_FATAL(content); - if (!linphone_content_is_multipart(content)) { + if (!linphone_content_is_multipart(content) && (!ua || !strstr(ua, "flexisip"))) { /*disable check for full presence serveur support*/ /*hack to disable content checking for list notify */ BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content)); } diff --git a/tester/flexisip/flexisip.conf b/tester/flexisip/flexisip.conf index 5943e57a3..9aaceda2f 100644 --- a/tester/flexisip/flexisip.conf +++ b/tester/flexisip/flexisip.conf @@ -617,6 +617,7 @@ ban-time=1 [module::Presence] enabled=true presence-server = +only-list-subscription = !(user-agent contains 'full-presence-support') [presence-server] expires = 600 diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 6b4060e0b..77815e847 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -21,6 +21,8 @@ #include "private.h" #include "liblinphone_tester.h" +static void enable_publish(LinphoneCoreManager *mgr, bool_t enable); + static LinphoneCoreManager* presence_linphone_core_manager_new(char* username) { LinphoneCoreManager* mgr= linphone_core_manager_new2( "empty_rc", FALSE); char* identity_char; @@ -400,25 +402,25 @@ static void subscribe_presence_expired(void){ lcs = ms_list_append(lcs, pauline1->lc); lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 10); - + lf = linphone_core_create_friend(marie->lc); linphone_friend_set_address(lf, pauline1->identity); linphone_friend_enable_subscribes(lf, TRUE); linphone_core_add_friend(marie->lc, lf); linphone_friend_unref(lf); - BC_ASSERT_TRUE(wait_for_list(lcs,&pauline1->stat.number_of_NewSubscriptionRequest,1, 5000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,1, 2000)); lf = linphone_core_find_friend(pauline1->lc, marie->identity); BC_ASSERT_PTR_NOT_NULL(lf->insubs); + /*marie comes offline suddenly*/ linphone_core_set_network_reachable(marie->lc, FALSE); /*after a certain time, pauline shall see the incoming SUBSCRIBE expired*/ wait_for_list(lcs,NULL, 0, 11000); - BC_ASSERT_PTR_NULL(lf->insubs); + /*just make network reachable so that marie can unregister properly*/ linphone_core_set_network_reachable(marie->lc, TRUE); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneRegistrationOk,2, 10000)); @@ -428,20 +430,71 @@ static void subscribe_presence_expired(void){ ms_list_free(lcs); } +static void subscriber_no_longuer_reachable(void){ + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline1 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneFriend *lf; + MSList *lcs = NULL; + LinphonePresenceModel * presence; + + lcs = ms_list_append(lcs, marie->lc); + lcs = ms_list_append(lcs, pauline1->lc); + + lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); + linphone_core_set_user_agent(pauline1->lc, "full-presence-support", NULL); + + enable_publish(pauline1, TRUE); + + lf = linphone_core_create_friend(marie->lc); + linphone_friend_set_address(lf, pauline1->identity); + linphone_friend_enable_subscribes(lf, TRUE); + + linphone_core_add_friend(marie->lc, lf); + linphone_friend_unref(lf); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,1, 2000)); + + + presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL); + linphone_core_set_presence_model(pauline1->lc,presence); -#define USE_PRESENCE_SERVER 0 + /*don't schedule marie to simulate Notify timeout server side*/ + wait_for_until(pauline1->lc, NULL, 0, 0, 35000); + + //sal_set_send_error(marie->lc->sal,0); + + /*because of notify timeout detected by server, so subscription is reset*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOffline,2, 4000)); + + // now subscribetion is supposed to be dead because notify was not answered in time. + presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityOnline,NULL); + linphone_core_set_presence_model(pauline1->lc,presence); + + /*becasue subscription is automatically restarted*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,2, 4000)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline1); + + ms_list_free(lcs); + +} -#if USE_PRESENCE_SERVER static void test_subscribe_notify_publish(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); LinphoneProxyConfig* proxy; LinphonePresenceModel* presence; + LpConfig *pauline_lp; + char* lf_identity; + LinphoneFriend *lf; - LpConfig *pauline_lp = linphone_core_get_config(pauline->lc); - char* lf_identity=linphone_address_as_string_uri_only(marie->identity); - LinphoneFriend *lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity); + linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); + linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); + pauline_lp = linphone_core_get_config(pauline->lc); + lf_identity=linphone_address_as_string_uri_only(marie->identity); + lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity); lp_config_set_int(pauline_lp,"sip","subscribe_expires",5); @@ -453,7 +506,7 @@ static void test_subscribe_notify_publish(void) { /*enable publish*/ - linphone_core_get_default_proxy(marie->lc,&proxy); + proxy = linphone_core_get_default_proxy_config(marie->lc); linphone_proxy_config_edit(proxy); linphone_proxy_config_enable_publish(proxy,TRUE); @@ -502,7 +555,11 @@ static void test_forked_subscribe_notify_publish(void) { lcs=ms_list_append(lcs,marie->lc); lcs=ms_list_append(lcs,marie->lc); lcs=ms_list_append(lcs,marie2->lc); + linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); + linphone_core_set_user_agent(marie2->lc, "full-presence-support", NULL); + linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); + pauline_lp = linphone_core_get_config(pauline->lc); lf_identity=linphone_address_as_string_uri_only(marie->identity); lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity); @@ -546,16 +603,14 @@ static void test_forked_subscribe_notify_publish(void) { linphone_core_set_presence_model(marie2->lc,presence); /*wait for new status*/ wait_for_list(lcs,&pauline->stat.number_of_NotifyPresenceReceived,5,2000); - BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d"); /*because liblinphone compositor is very simple for now (I.E only take first occurence)*/ + BC_ASSERT_TRUE(LinphoneStatusBusy == linphone_friend_get_status(lf) + || LinphoneStatusDoNotDisturb == linphone_friend_get_status(lf)); /*because liblinphone compositor is very simple for now */ linphone_core_manager_destroy(marie); linphone_core_manager_destroy(marie2); linphone_core_manager_destroy(pauline); } - -#endif - const char * get_identity(LinphoneCoreManager *mgr) { LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(mgr->lc); return linphone_proxy_config_get_identity(cfg); @@ -692,7 +747,7 @@ static void test_presence_list(void) { linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } - +#if 0 static void test_presence_list_subscribe_before_publish(void) { LinphoneCoreManager *laure = linphone_core_manager_new("laure_tcp_rc"); LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); @@ -742,8 +797,8 @@ static void test_presence_list_subscribe_before_publish(void) { linphone_core_manager_destroy(laure); linphone_core_manager_destroy(pauline); } - -static void test_presence_list_subscription_expire(void) { +#endif +static void test_presence_list_subscription_expire_for_unknown(void) { LinphoneCoreManager *laure = linphone_core_manager_new("laure_tcp_rc"); const char *rls_uri = "sip:rls@sip.example.org"; LinphoneFriendList *lfl; @@ -762,16 +817,77 @@ static void test_presence_list_subscription_expire(void) { /* wait for refresh*/ BC_ASSERT_FALSE(wait_for_until(laure->lc, NULL, &laure->stat.number_of_NotifyPresenceReceived, 1, 4000)); - /*sal_set_send_error(laure->lc->sal,1500);*/ /*make sure no refresh is sent, trash the message without generating error*/ - - /*make sure we don't received any notify, even when subscribtion has expired*/ - /*BC_ASSERT_FALSE(wait_for_until(laure->lc, NULL, &laure->stat.number_of_NotifyPresenceReceived, 1, 5000)); - - sal_set_send_error(laure->lc->sal,0);*/ - linphone_core_manager_destroy(laure); } +static void test_presence_list_subscribe_dialog_expire(void) { + LinphoneCoreManager *laure = linphone_core_manager_new("laure_tcp_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); + const char *rls_uri = "sip:rls@sip.example.org"; + LinphoneFriendList *lfl; + LinphoneFriend *lf; + const char *pauline_identity; + MSList* lcs = NULL; + int dummy = 0; + lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 3); + + + pauline_identity = get_identity(pauline); + + linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL)); + + lfl = linphone_core_create_friend_list(laure->lc); + linphone_friend_list_set_rls_uri(lfl, rls_uri); + lf = linphone_core_create_friend_with_address(laure->lc, pauline_identity); + linphone_friend_list_add_friend(lfl, lf); + lf = linphone_core_create_friend_with_address(laure->lc, "sip:michelle@sip.inexistentdomain.com"); + linphone_friend_list_add_friend(lfl, lf); + linphone_core_set_friend_list(laure->lc, lfl); + linphone_friend_list_unref(lfl); + linphone_core_set_presence_model(laure->lc, linphone_core_create_presence_model_with_activity(laure->lc, LinphonePresenceActivityOnline, NULL)); + linphone_friend_list_update_subscriptions(laure->lc->friendlist, NULL, FALSE); + + lcs = ms_list_append(lcs, laure->lc); + lcs = ms_list_append(lcs, pauline->lc); + + wait_for_list(lcs, &dummy, 1, 2000); /* Wait a little bit for the subscribe to happen */ + + enable_publish(pauline, TRUE); + wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 1, 2000); + BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); + BC_ASSERT_GREATER(laure->lc->friendlist->expected_notification_version, 1, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, pauline_identity); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d"); + BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d"); + BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, "sip:michelle@sip.inexistentdomain.com"); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d"); + BC_ASSERT_EQUAL(lf->presence_received, FALSE, int, "%d"); + BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + + BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_NotifyPresenceReceived, 2, 5000)); + ms_message("Simulating in/out packets losses"); + sal_set_send_error(laure->lc->sal,1500); /*make sure no refresh is sent, trash the message without generating error*/ + sal_set_recv_error(laure->lc->sal, 1500); /*make sure server notify to close the dialog is also ignored*/ + + wait_for_list(lcs, &dummy, 1, 3000); /* Wait a little bit for the subscribe to happen */ + + /*restart normal behavior*/ + sal_set_send_error(laure->lc->sal,0); + sal_set_recv_error(laure->lc->sal, 1); + + + linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityAway, NULL)); + + BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_NotifyPresenceReceived, 3, 5000)); + lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, pauline_identity); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusAway, int, "%d"); + + linphone_core_manager_destroy(laure); + linphone_core_manager_destroy(pauline); +} + + test_t presence_tests[] = { TEST_NO_TAG("Simple Subscribe", simple_subscribe), @@ -783,13 +899,12 @@ test_t presence_tests[] = { TEST_NO_TAG("App managed presence failure", subscribe_failure_handle_by_app), TEST_NO_TAG("Presence SUBSCRIBE forked", subscribe_presence_forked), TEST_NO_TAG("Presence SUBSCRIBE expired", subscribe_presence_expired), -#if USE_PRESENCE_SERVER + TEST_NO_TAG("Subscriber no loguer reachable using server",subscriber_no_longuer_reachable), TEST_NO_TAG("Subscribe with late publish", test_subscribe_notify_publish), TEST_NO_TAG("Forked subscribe with late publish", test_forked_subscribe_notify_publish), -#endif TEST_NO_TAG("Presence list", test_presence_list), - TEST_NO_TAG("Presence list (subscribe before publish)", test_presence_list_subscribe_before_publish), - TEST_NO_TAG("Presence list, subscription expiration",test_presence_list_subscription_expire) + TEST_NO_TAG("Presence list, subscription expiration for unknown contact",test_presence_list_subscription_expire_for_unknown), + TEST_NO_TAG("Presence list, silent subscription expiration", test_presence_list_subscribe_dialog_expire) }; test_suite_t presence_test_suite = {"Presence", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/register_tester.c b/tester/register_tester.c index 4397b3011..a8fa71a82 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -216,7 +216,7 @@ static void simple_unregister(void){ LinphoneProxyConfig* proxy_config; register_with_refresh_base(lcm->lc,FALSE,NULL,NULL); - linphone_core_get_default_proxy(lcm->lc,&proxy_config); + proxy_config = linphone_core_get_default_proxy_config(lcm->lc); linphone_proxy_config_edit(proxy_config); reset_counters(counters); /*clear stats*/ diff --git a/tester/tester.c b/tester/tester.c index bb689f5b1..08f010dc0 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -255,11 +255,6 @@ bool_t transport_supported(LinphoneTransportType transport) { return supported; } - -static void display_status(LinphoneCore *lc, const char *status){ - ms_message("display_status(): %s",status); -} - void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file) { char *rc_path = NULL; char *hellopath = bc_tester_res("sounds/hello8000.wav"); @@ -282,7 +277,6 @@ void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file) { mgr->v_table.network_reachable=network_reachable; mgr->v_table.dtmf_received=dtmf_received; mgr->v_table.call_stats_updated=call_stats_updated; - mgr->v_table.display_status=display_status; reset_counters(&mgr->stat); if (rc_file) rc_path = ms_strdup_printf("rcfiles/%s", rc_file); @@ -354,7 +348,7 @@ void linphone_core_manager_start(LinphoneCoreManager *mgr, int check_for_proxies BC_ASSERT_EQUAL(mgr->stat.number_of_LinphoneRegistrationOk,proxy_count, int, "%d"); enable_codec(mgr->lc,"PCMU",8000); - linphone_core_get_default_proxy(mgr->lc,&proxy); + proxy = linphone_core_get_default_proxy_config(mgr->lc); if (proxy) { mgr->identity = linphone_address_clone(linphone_proxy_config_get_identity_address(proxy)); linphone_address_clean(mgr->identity); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 545ac16b8..88cd09173 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -75,3 +75,26 @@ install(TARGETS lp-auto-answer PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) +set(LP_SENDMSG_SOURCE_FILES + lpsendmsg.c +) + +add_definitions( + -DIN_LINPHONE +) + +apply_compile_flags(LP_SENDMSG_SOURCE_FILES "CPP" "C") +add_executable(lp-sendmsg ${LP_SENDMSG_SOURCE_FILES}) +target_link_libraries(lp-sendmsg linphone) + + +install(TARGETS lp-sendmsg + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + + + + diff --git a/tools/Makefile.am b/tools/Makefile.am index 8a2c21436..f59617a43 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -19,7 +19,7 @@ EXTRA_DIST=xml2lpc_jni.cc lpc2xml_jni.cc if BUILD_TOOLS -bin_PROGRAMS=xml2lpc_test lpc2xml_test lp-gen-wrappers lp-autoanswer lp-test-ecc +bin_PROGRAMS=xml2lpc_test lpc2xml_test lp-gen-wrappers lp-autoanswer lp-test-ecc lp-sendmsg xml2lpc_test_SOURCES=\ xml2lpc_test.c @@ -52,6 +52,10 @@ lp_test_ecc_SOURCES=test_ecc.c lp_test_ecc_CFLAGS=$(COMMON_CFLAGS) lp_test_ecc_LDADD=$(top_builddir)/coreapi/liblinphone.la +lp_sendmsg_SOURCES=lpsendmsg.c +lp_sendmsg_CFLAGS=$(COMMON_CFLAGS) +lp_sendmsg_LDADD=$(top_builddir)/coreapi/liblinphone.la + endif diff --git a/tools/lpsendmsg.c b/tools/lpsendmsg.c new file mode 100644 index 000000000..a88407055 --- /dev/null +++ b/tools/lpsendmsg.c @@ -0,0 +1,197 @@ +/* +linphone +Copyright (C) 2016 Belledonne Communications SARL + (simon.morlat@linphone.org) + +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, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#ifdef IN_LINPHONE +#include "linphonecore.h" +#else +#include "linphone/linphonecore.h" +#endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +static bool_t running = TRUE; +static const char *passwd = NULL; + +static void stop(int signum){ + running=FALSE; +} + +static void helper(const char *progname) { + printf("%s --from --to --route --passwd --text \n" + "\t\t\t--help\n" + "\t\t\t--from uri to send from\n" + "\t\t\t--to uri to send to\n" + "\t\t\t--route uri to send the message through\n" + "\t\t\t--passwd \n" + "\t\t\t--text \n" + "\t\t\t--verbose\n", progname); + exit(0); +} + +static void on_msg_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state){ + switch(state){ + case LinphoneChatMessageStateInProgress: + printf("Sending message...\n"); + break; + case LinphoneChatMessageStateNotDelivered: + fprintf(stderr, "Error sending message. Use --verbose to troubleshoot.\n"); + running = FALSE; + break; + case LinphoneChatMessageStateDelivered: + printf("Message transmitted succesfully.\n"); + running = FALSE; + break; + case LinphoneChatMessageStateFileTransferDone: + case LinphoneChatMessageStateFileTransferError: + case LinphoneChatMessageStateIdle: + break; + } +} + +static void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain){ + running = FALSE; + if (passwd){ + fprintf(stderr, "Server rejected the supplied username or password\n"); + }else{ + fprintf(stderr, "Authentication requested by server. Please retry by supplying a password with --passwd.\n"); + } +} + +int main(int argc, char *argv[]){ + LinphoneCoreVTable vtable={0}; + LinphoneCore *lc; + int i; + LinphoneAddress *from = NULL; + LinphoneAddress *to = NULL; + LinphoneAddress *route = NULL; + LinphoneProxyConfig *cfg; + LinphoneChatMessage *msg; + LinphoneChatRoom *room; + LinphoneChatMessageCbs *cbs; + char * text = NULL; + char *tmp; + + signal(SIGINT,stop); + + for(i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--verbose") == 0) { + linphone_core_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL); + } else if (strcmp(argv[i], "--from") == 0){ + i++; + if (i < argc){ + from = linphone_address_new(argv[i]); + if (!from) { + fprintf(stderr, "Incorrect from specified\n"); + return -1; + } + } + } else if (strcmp(argv[i], "--to") == 0){ + i++; + if (i < argc){ + to = linphone_address_new(argv[i]); + if (!to) { + fprintf(stderr, "Incorrect to specified\n"); + return -1; + } + } + }else if (strcmp(argv[i], "--route") == 0){ + i++; + if (i < argc){ + route = linphone_address_new(argv[i]); + if (!route) { + fprintf(stderr, "Incorrect route specified\n"); + return -1; + } + } + } else if (strcmp(argv[i], "--passwd") == 0){ + i++; + if (i < argc){ + passwd = argv[i]; + } + } else if (strcmp(argv[i], "--text") == 0){ + i++; + if (i < argc){ + text = argv[i]; + } + } else { + helper(argv[0]); + } + } + + if (!from) { + fprintf(stderr, "Please specify from.\n"); + helper(argv[0]); + return -1; + } + if (!to) { + fprintf(stderr, "Please specify to.\n"); + helper(argv[0]); + return -1; + } + if (!text){ + fprintf(stderr, "Please specify text to send.\n"); + helper(argv[0]); + return -1; + } + + vtable.auth_info_requested = auth_info_requested; + lc=linphone_core_new(&vtable,NULL, NULL, NULL); + + if (passwd){ + LinphoneAuthInfo *ai = linphone_core_create_auth_info(lc, linphone_address_get_username(from), NULL, passwd, NULL, NULL, NULL); + linphone_core_add_auth_info(lc, ai); + linphone_auth_info_destroy(ai); + } + + if (!route){ + route = linphone_address_clone(from); + linphone_address_set_username(route, NULL); + linphone_address_set_display_name(route, NULL); + } + + cfg = linphone_core_create_proxy_config(lc); + linphone_proxy_config_set_identity_address(cfg, from); + tmp = linphone_address_as_string(route); + linphone_proxy_config_set_server_addr(cfg, tmp); + ms_free(tmp); + linphone_proxy_config_enable_register(cfg, FALSE); + linphone_core_add_proxy_config(lc, cfg); + linphone_proxy_config_unref(cfg); + + room = linphone_core_get_chat_room(lc, to); + msg = linphone_chat_room_create_message(room, text); + cbs = linphone_chat_message_get_callbacks(msg); + linphone_chat_message_cbs_set_msg_state_changed(cbs, on_msg_state_changed); + linphone_chat_room_send_chat_message(room, msg); + /* main loop for receiving notifications and doing background linphonecore work: */ + while(running){ + linphone_core_iterate(lc); + ms_usleep(50000); + } + linphone_address_destroy(from); + linphone_address_destroy(to); + linphone_address_destroy(route); + linphone_core_destroy(lc); + return 0; +} +