Commit fed41550 authored by Simon Morlat's avatar Simon Morlat

enhance event API to be notified of publish states.

lp-gen-wrappers is in progress
parent f9e07825
......@@ -174,7 +174,8 @@ static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *e
}
}
static void process_request_event(void *sal, const belle_sip_request_event_t *event) {
static void process_request_event(void *ud, const belle_sip_request_event_t *event) {
Sal *sal=(Sal*)ud;
SalOp* op=NULL;
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event);
......@@ -195,36 +196,41 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev
return;
}
}else if (strcmp("INVITE",method)==0) {
op=sal_op_new((Sal*)sal);
op=sal_op_new(sal);
op->dir=SalOpDirIncoming;
sal_op_call_fill_cbs(op);
}else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) {
op=sal_op_new((Sal*)sal);
op=sal_op_new(sal);
op->dir=SalOpDirIncoming;
if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){
sal_op_presence_fill_cbs(op);
}else
sal_op_subscribe_fill_cbs(op);
}else if (strcmp("MESSAGE",method)==0) {
op=sal_op_new((Sal*)sal);
op=sal_op_new(sal);
op->dir=SalOpDirIncoming;
sal_op_message_fill_cbs(op);
}else if (strcmp("OPTIONS",method)==0) {
resp=belle_sip_response_create_from_request(req,200);
belle_sip_provider_send_response(((Sal*)sal)->prov,resp);
belle_sip_provider_send_response(sal->prov,resp);
return;
}else if (strcmp("INFO",method)==0) {
resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/
belle_sip_provider_send_response(((Sal*)sal)->prov,resp);
belle_sip_provider_send_response(sal->prov,resp);
return;
}else if (strcmp("BYE",method)==0) {
resp=belle_sip_response_create_from_request(req,481);/*out of dialog BYE */
belle_sip_provider_send_response(((Sal*)sal)->prov,resp);
belle_sip_provider_send_response(sal->prov,resp);
return;
}else if (sal->enable_test_features && strcmp("PUBLISH",method)==0) {
resp=belle_sip_response_create_from_request(req,200);/*out of dialog BYE */
belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_header_create("SIP-Etag","4441929FFFZQOA"));
belle_sip_provider_send_response(sal->prov,resp);
return;
}else {
ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req));
resp=belle_sip_response_create_from_request(req,501);
belle_sip_provider_send_response(((Sal*)sal)->prov,resp);
belle_sip_provider_send_response(sal->prov,resp);
return;
}
......@@ -460,6 +466,10 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
if (ctx->callbacks.info_received==NULL)
ctx->callbacks.info_received=(SalOnInfoReceived)unimplemented_stub;
if (ctx->callbacks.on_publish_response==NULL)
ctx->callbacks.on_publish_response=(SalOnPublishResponse)unimplemented_stub;
if (ctx->callbacks.on_expire==NULL)
ctx->callbacks.on_expire=(SalOnExpire)unimplemented_stub;
}
......@@ -825,3 +835,8 @@ int sal_get_refresher_retry_after(const Sal *sal) {
void sal_enable_auto_contacts(Sal *ctx, bool_t enabled){
ctx->auto_contacts=enabled;
}
void sal_enable_test_features(Sal*ctx, bool_t enabled){
ctx->enable_test_features=enabled;
}
......@@ -46,6 +46,7 @@ struct Sal{
bool_t tls_verify_cn;
bool_t use_dates;
bool_t auto_contacts;
bool_t enable_test_features;
};
typedef enum SalOpState {
......
......@@ -22,11 +22,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void subscribe_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
ms_error("subscribe_process_io_error not implemented yet");
}
static void subscribe_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) {
SalOp* op= (SalOp*)ctx;
if (op->dialog) {
sal_op_unref(op);
op->dialog=NULL;
sal_op_unref(op);
}
}
......
......@@ -407,10 +407,15 @@ void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal
*sal_reason=SalReasonServiceUnavailable;
break;
default:
if (code>0){
if (code>=300){
*sal_err=SalErrorFailure;
*sal_reason=SalReasonUnknown;
}else *sal_err=SalErrorNoResponse;
}else if (code>=100){
*sal_err=SalErrorNone;
*sal_reason=SalReasonUnknown;
}else if (code==0){
*sal_err=SalErrorNoResponse;
}
/* no break */
}
}
......
......@@ -56,7 +56,7 @@ static void presence_process_dialog_terminated(void *ctx, const belle_sip_dialog
}
}
static void presence_refresher_listener( const belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase){
static void presence_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase){
SalOp* op = (SalOp*)user_pointer;
switch(status_code){
case 481: {
......
......@@ -19,21 +19,43 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sal_impl.h"
static void publish_refresher_listener ( const belle_sip_refresher_t* refresher
static void publish_refresher_listener (belle_sip_refresher_t* refresher
,void* user_pointer
,unsigned int status_code
,const char* reason_phrase) {
SalOp* op = (SalOp*)user_pointer;
/*belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));*/
ms_message("Publish refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op));
ms_message("Publish refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase?reason_phrase:"none",sal_op_get_proxy(op));
if (status_code==412){
/*resubmit the request after removing the SIP-If-Match*/
const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
belle_sip_message_remove_header((belle_sip_message_t*)last_publish,"SIP-If-Match");
belle_sip_refresher_refresh(op->refresher,BELLE_SIP_REFRESHER_REUSE_EXPIRES);
}else if (status_code==0){
op->base.root->callbacks.on_expire(op);
}else if (status_code>=200){
SalError err;
SalReason reason;
sal_compute_sal_errors_from_code(status_code,&err,&reason);
op->base.root->callbacks.on_publish_response(op,err,reason);
}
}
static void publish_response_event(void *userctx, const belle_sip_response_event_t *event){
SalOp *op=(SalOp*)userctx;
int code=belle_sip_response_get_status_code(belle_sip_response_event_get_response(event));
SalError err;
SalReason reason;
sal_compute_sal_errors_from_code(code,&err,&reason);
op->base.root->callbacks.on_publish_response(op,err,reason);
}
void sal_op_publish_fill_cbs(SalOp*op) {
op->callbacks.process_response_event=publish_response_event;
op->type=SalOpPublish;
}
/*presence publish */
int sal_publish_presence(SalOp *op, const char *from, const char *to, int expires, SalPresenceModel *presence){
belle_sip_request_t *req=NULL;
......@@ -68,7 +90,7 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna
if (to)
sal_op_set_to(op,to);
op->type=SalOpPublish;
sal_op_publish_fill_cbs(op);
req=sal_op_build_request(op,"PUBLISH");
if (sal_op_get_contact(op)){
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op)));
......@@ -82,8 +104,6 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna
belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
/*update body*/
sal_op_add_body(op,BELLE_SIP_MESSAGE(last_publish),body);
return belle_sip_refresher_refresh(op->refresher,BELLE_SIP_REFRESHER_REUSE_EXPIRES);
return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires);
}
}
......@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sal_impl.h"
static void register_refresher_listener ( const belle_sip_refresher_t* refresher
static void register_refresher_listener (belle_sip_refresher_t* refresher
,void* user_pointer
,unsigned int status_code
,const char* reason_phrase) {
......
......@@ -1086,6 +1086,32 @@ static void subscribe_closed(SalOp *op){
linphone_event_set_state(lev,LinphoneSubscriptionTerminated);
}
static void on_publish_response(SalOp* op, SalError err, SalReason reason){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
if (lev==NULL) return;
if (err==SalErrorNone){
if (!lev->terminating)
linphone_event_set_publish_state(lev,LinphonePublishOk);
else
linphone_event_set_publish_state(lev,LinphonePublishCleared);
}else{
linphone_event_set_reason(lev,linphone_reason_from_sal(reason));
linphone_event_set_publish_state(lev,LinphonePublishError);
}
}
static void on_expire(SalOp *op){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
if (lev==NULL) return;
if (linphone_event_get_publish_state(lev)==LinphonePublishOk){
linphone_event_set_publish_state(lev,LinphonePublishExpiring);
}
}
SalCallbacks linphone_sal_callbacks={
call_received,
call_ringing,
......@@ -1120,7 +1146,9 @@ SalCallbacks linphone_sal_callbacks={
notify_presence,
ping_reply,
auth_requested,
info_received
info_received,
on_publish_response,
on_expire
};
......@@ -20,18 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "private.h"
#include "lpconfig.h"
struct _LinphoneEvent{
LinphoneSubscriptionDir dir;
LinphoneCore *lc;
SalOp *op;
LinphoneSubscriptionState state;
LinphoneReason reason;
void *userdata;
int refcnt;
char *name;
LinphoneAddress *from;
LinphoneAddress *resource_addr;
};
LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss){
switch(ss){
......@@ -43,6 +31,31 @@ LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatu
return LinphoneSubscriptionNone;
}
const char *linphone_subscription_state_to_string(LinphoneSubscriptionState state){
switch(state){
case LinphoneSubscriptionNone: return "LinphoneSubscriptionNone";
case LinphoneSubscriptionIncomingReceived: return "LinphoneSubscriptionIncomingReceived";
case LinphoneSubscriptionOutoingInit: return "LinphoneSubscriptionOutoingInit";
case LinphoneSubscriptionPending: return "LinphoneSubscriptionPending";
case LinphoneSubscriptionActive: return "LinphoneSubscriptionActive";
case LinphoneSubscriptionTerminated: return "LinphoneSubscriptionTerminated";
case LinphoneSubscriptionError: return "LinphoneSubscriptionError";
}
return NULL;
}
LINPHONE_PUBLIC const char *linphone_publish_state_to_string(LinphonePublishState state){
switch(state){
case LinphonePublishNone: return "LinphonePublishNone";
case LinphonePublishProgress: return "LinphonePublishProgress";
case LinphonePublishOk: return "LinphonePublishOk";
case LinphonePublishError: return "LinphonePublishError";
case LinphonePublishCleared: return "LinphonePublishCleared";
case LinphonePublishExpiring: return "LinphonePublishExpiring";
}
return NULL;
}
static LinphoneEvent * linphone_event_new_base(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, SalOp *op){
LinphoneEvent *lev=ms_new0(LinphoneEvent,1);
lev->lc=lc;
......@@ -72,8 +85,9 @@ LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneS
void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state){
LinphoneCore *lc=lev->lc;
if (lev->state!=state){
lev->state=state;
if (lev->subscription_state!=state){
ms_message("LinphoneEvent [%p] moving to subscription state %s",lev,linphone_subscription_state_to_string(state));
lev->subscription_state=state;
if (lc->vtable.subscription_state_changed){
lc->vtable.subscription_state_changed(lev->lc,lev,state);
}
......@@ -83,6 +97,21 @@ void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState stat
}
}
void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state){
LinphoneCore *lc=lev->lc;
if (lev->publish_state!=state){
ms_message("LinphoneEvent [%p] moving to publish state %s",lev,linphone_publish_state_to_string(state));
lev->publish_state=state;
if (lc->vtable.publish_state_changed){
lc->vtable.publish_state_changed(lev->lc,lev,state);
}
}
}
LinphonePublishState linphone_event_get_publish_state(const LinphoneEvent *lev){
return lev->publish_state;
}
void linphone_event_set_reason(LinphoneEvent *lev, LinphoneReason reason){
lev->reason=reason;
}
......@@ -105,7 +134,7 @@ LinphoneEvent *linphone_core_subscribe(LinphoneCore *lc, const LinphoneAddress *
int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *body){
SalBody salbody;
if (lev->state!=LinphoneSubscriptionActive){
if (lev->subscription_state!=LinphoneSubscriptionActive){
ms_error("linphone_event_update_subscribe(): cannot update subscription if subscription wasn't accepted.");
return -1;
}
......@@ -118,7 +147,7 @@ int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *b
int linphone_event_accept_subscription(LinphoneEvent *lev){
int err;
if (lev->state!=LinphoneSubscriptionIncomingReceived){
if (lev->subscription_state!=LinphoneSubscriptionIncomingReceived){
ms_error("linphone_event_accept_subscription(): cannot accept subscription if subscription wasn't just received.");
return -1;
}
......@@ -131,7 +160,7 @@ int linphone_event_accept_subscription(LinphoneEvent *lev){
int linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReason reason){
int err;
if (lev->state!=LinphoneSubscriptionIncomingReceived){
if (lev->subscription_state!=LinphoneSubscriptionIncomingReceived){
ms_error("linphone_event_deny_subscription(): cannot deny subscription if subscription wasn't just received.");
return -1;
}
......@@ -142,7 +171,7 @@ int linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReason reason){
int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){
SalBody salbody;
if (lev->state!=LinphoneSubscriptionActive){
if (lev->subscription_state!=LinphoneSubscriptionActive){
ms_error("linphone_event_notify(): cannot notify if subscription is not active.");
return -1;
}
......@@ -155,17 +184,30 @@ int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){
LinphoneEvent *linphone_core_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires, const LinphoneContent *body){
SalBody salbody;
int err;
LinphoneEvent *lev=linphone_event_new(lc,LinphoneSubscriptionInvalidDir, event);
linphone_configure_op(lc,lev->op,resource,NULL,lp_config_get_int(lc->config,"sip","publish_msg_with_contact",0));
sal_op_set_manual_refresher_mode(lev->op,lp_config_get_int(lc->config,"sip","refresh_generic_publish",1));
sal_publish(lev->op,NULL,NULL,event,expires,sal_body_from_content(&salbody,body));
err=sal_publish(lev->op,NULL,NULL,event,expires,sal_body_from_content(&salbody,body));
if (err==0){
linphone_event_set_publish_state(lev,LinphonePublishProgress);
}else{
linphone_event_unref(lev);
lev=NULL;
}
return lev;
}
int linphone_event_update_publish(LinphoneEvent *lev, const LinphoneContent *body){
SalBody salbody;
return sal_publish(lev->op,NULL,NULL,NULL,-1,sal_body_from_content(&salbody,body));
int err;
err=sal_publish(lev->op,NULL,NULL,NULL,-1,sal_body_from_content(&salbody,body));
if (err==0){
linphone_event_set_publish_state(lev,LinphonePublishProgress);
}else{
linphone_event_set_publish_state(lev,LinphonePublishError);
}
return err;
}
void linphone_event_set_user_data(LinphoneEvent *ev, void *up){
......@@ -177,15 +219,25 @@ void *linphone_event_get_user_data(const LinphoneEvent *ev){
}
void linphone_event_terminate(LinphoneEvent *lev){
lev->terminating=TRUE;
if (lev->dir==LinphoneSubscriptionIncoming){
sal_notify_close(lev->op);
}else if (lev->dir==LinphoneSubscriptionOutgoing){
sal_unsubscribe(lev->op);
}
if (lev->state!=LinphoneSubscriptionNone){
if (lev->publish_state!=LinphonePublishNone){
if (lev->publish_state==LinphonePublishOk){
sal_publish(lev->op,NULL,NULL,NULL,0,NULL);
}
return;
}
if (lev->subscription_state!=LinphoneSubscriptionNone){
linphone_event_set_state(lev,LinphoneSubscriptionTerminated);
return;
}
}
......@@ -213,7 +265,7 @@ LinphoneSubscriptionDir linphone_event_get_subscription_dir(LinphoneEvent *lev){
}
LinphoneSubscriptionState linphone_event_get_subscription_state(const LinphoneEvent *lev){
return lev->state;
return lev->subscription_state;
}
const char *linphone_event_get_name(const LinphoneEvent *lev){
......
......@@ -26,6 +26,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
struct _LinphoneEvent;
/**
* Object representing an event state, which is subcribed or published.
* @see linphone_core_publish()
* @see linphone_core_subscribe()
**/
typedef struct _LinphoneEvent LinphoneEvent;
/**
......@@ -55,8 +60,32 @@ enum _LinphoneSubscriptionState{
LinphoneSubscriptionError /**<Subscription encountered an error, indicated by linphone_event_get_reason()*/
};
/**
* Typedef for subscription state enum.
**/
typedef enum _LinphoneSubscriptionState LinphoneSubscriptionState;
LINPHONE_PUBLIC const char *linphone_subscription_state_to_string(LinphoneSubscriptionState state);
/**
* Enum for publish states.
**/
enum _LinphonePublishState{
LinphonePublishNone, /**< Initial state, do not use**/
LinphonePublishProgress, /**<An outgoing subcription was created*/
LinphonePublishOk, /**<Publish is accepted.*/
LinphonePublishError, /**<Publish encoutered an error, linphone_event_get_reason() gives reason code*/
LinphonePublishExpiring, /**<Publish is about to expire, only sent if [sip]->refresh_generic_publish property is set to 0.*/
LinphonePublishCleared /**<Event has been un published*/
};
/**
* Typedef for publish state enum
**/
typedef enum _LinphonePublishState LinphonePublishState;
LINPHONE_PUBLIC const char *linphone_publish_state_to_string(LinphonePublishState state);
/**
* Callback prototype for notifying the application about notification received from the network.
**/
......@@ -67,6 +96,11 @@ typedef void (*LinphoneEventIncomingNotifyCb)(LinphoneCore *lc, LinphoneEvent *l
**/
typedef void (*LinphoneSubscriptionStateChangedCb)(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state);
/**
* Callback prototype for notifying the application about changes of publish states.
**/
typedef void (*LinphonePublishStateChangedCb)(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state);
/**
* Create an outgoing subscription, specifying the destination resource, the event name, and an optional content body.
* If accepted, the subscription runs for a finite period, but is automatically renewed if not terminated before.
......@@ -105,7 +139,7 @@ LINPHONE_PUBLIC int linphone_event_notify(LinphoneEvent *lev, const LinphoneCont
/**
* Publish an event.
* Publish an event state.
* After expiry, the publication is refreshed unless it is terminated before.
* @param lc the #LinphoneCore
* @param resource the resource uri for the event
......@@ -134,6 +168,11 @@ LINPHONE_PUBLIC LinphoneReason linphone_event_get_reason(const LinphoneEvent *le
**/
LINPHONE_PUBLIC LinphoneSubscriptionState linphone_event_get_subscription_state(const LinphoneEvent *lev);
/**
* Get publish state. If the event object was not created by a publish mechanism, #LinphonePublishNone is returned.
**/
LINPHONE_PUBLIC LinphonePublishState linphone_event_get_publish_state(const LinphoneEvent *lev);
/**
* Get subscription direction.
* If the object wasn't created by a subscription mechanism, #LinphoneSubscriptionInvalidDir is returned.
......@@ -152,17 +191,26 @@ LINPHONE_PUBLIC void *linphone_event_get_user_data(const LinphoneEvent *ev);
/**
* Terminate an incoming or outgoing subscription that was previously acccepted, or a previous publication.
* This function does not unref the object. The core will unref() if it does not need this object anymore.
*
* For subscribed event, when the subscription is terminated normally or because of an error, the core will unref.
* For published events, no unref is performed. This is because it is allowed to re-publish an expired publish, as well as retry it in case of error.
**/
LINPHONE_PUBLIC void linphone_event_terminate(LinphoneEvent *lev);
/**
* Increase reference count.
* Increase reference count of LinphoneEvent.
* By default LinphoneEvents created by the core are owned by the core only.
* An application that wishes to retain a reference to it must call linphone_event_ref().
* When this reference is no longer needed, linphone_event_unref() must be called.
*
**/
LINPHONE_PUBLIC LinphoneEvent *linphone_event_ref(LinphoneEvent *lev);
/**
* Decrease reference count.
* @see linphone_event_ref()
**/
LINPHONE_PUBLIC void linphone_event_unref(LinphoneEvent *lev);
......
......@@ -273,12 +273,17 @@ LINPHONE_PUBLIC const rtp_stats_t *linphone_call_log_get_remote_stats(const Linp
LINPHONE_PUBLIC const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl);
LINPHONE_PUBLIC char * linphone_call_log_to_str(LinphoneCallLog *cl);
/**
* Private structure definition for LinphoneCallParams.
* @ingroup call_control
**/
struct _LinphoneCallParams;
/**
* The LinphoneCallParams is an object containing various call related parameters.
* It can be used to retrieve parameters from a currently running call or modify the call's characteristics
* dynamically.
* @ingroup call_control
**/
typedef struct _LinphoneCallParams LinphoneCallParams;
......@@ -1033,6 +1038,7 @@ typedef struct _LinphoneVTable{
LinphoneInfoReceivedCb info_received; /**<Notifies an incoming informational message received.*/
LinphoneSubscriptionStateChangedCb subscription_state_changed; /**<Notifies subscription state change */
LinphoneEventIncomingNotifyCb notify_received; /**< Notifies a an event notification, see linphone_core_subscribe() */
LinphonePublishStateChangedCb publish_state_changed;/**Notifies publish state change (only from #LinphoneEvent api)*/
DisplayStatusCb display_status; /**< @deprecated Callback that notifies various events with human readable text.*/
DisplayMessageCb display_message;/**< @deprecated Callback to display a message to the user */
DisplayMessageCb display_warning;/**< @deprecated Callback to display a warning to the user */
......
......@@ -652,6 +652,23 @@ struct _LinphoneCore
#endif //BUILD_UPNP
};
struct _LinphoneEvent{
LinphoneSubscriptionDir dir;
LinphoneCore *lc;
SalOp *op;
LinphoneSubscriptionState subscription_state;
LinphonePublishState publish_state;
LinphoneReason reason;
void *userdata;
int refcnt;
char *name;
LinphoneAddress *from;
LinphoneAddress *resource_addr;
bool_t terminating;
};
LinphoneTunnel *linphone_core_tunnel_new(LinphoneCore *lc);
void linphone_tunnel_destroy(LinphoneTunnel *tunnel);
void linphone_tunnel_configure(LinphoneTunnel *tunnel);
......@@ -759,6 +776,7 @@ LinphoneReason linphone_reason_from_sal(SalReason reason);
LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name);
LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name);
void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state);
void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state);
void linphone_event_set_reason(LinphoneEvent *lev, LinphoneReason reason);
LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss);
const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, const SalBody *ref);
......
......@@ -369,6 +369,8 @@ typedef void (*SalOnSubscribePresenceReceived)(SalOp *salop, const char *from);
typedef void (*SalOnSubscribePresenceClosed)(SalOp *salop, const char *from);
typedef void (*SalOnPingReply)(SalOp *salop);
typedef void (*SalOnInfoReceived)(SalOp *salop, const SalBody *body);
typedef void (*SalOnPublishResponse)(SalOp *salop, SalError error, SalReason reason);
typedef void (*SalOnExpire)(SalOp *salop);
/*allows sal implementation to access auth info if available, return TRUE if found*/
......@@ -408,6 +410,8 @@ typedef struct SalCallbacks{
SalOnPingReply ping_reply;
SalOnAuthRequested auth_requested;
SalOnInfoReceived info_received;
SalOnPublishResponse on_publish_response;
SalOnExpire on_expire;
}SalCallbacks;
......@@ -446,6 +450,7 @@ void sal_verify_server_certificates(Sal *ctx, bool_t verify);
void sal_verify_server_cn(Sal *ctx, bool_t verify);
void sal_set_uuid(Sal*ctx, const char *uuid);
int sal_create_uuid(Sal*ctx, char *uuid, size_t len);
void sal_enable_test_features(Sal*ctx, bool_t enabled);
int sal_iterate(Sal *sal);
MSList * sal_get_pending_auths(Sal *sal);
......
......@@ -20,6 +20,7 @@
#include "CUnit/Basic.h"
#include "linphonecore.h"
#include "private.h"
#include "lpconfig.h"
#include <event.h>
#include "liblinphone_tester.h"
......@@ -78,6 +79,20 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li
}
}
void linphone_publish_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state){
stats* counters = get_stats(lc);
switch(state){
case LinphonePublishProgress: counters->number_of_LinphonePublishProgress++; break;
case LinphonePublishOk: counters->number_of_LinphonePublishOk++; break;
case LinphonePublishError: counters->number_of_LinphonePublishError++; break;
case LinphonePublishExpiring: counters->number_of_LinphonePublishExpiring++; break;
case LinphonePublishCleared: counters->number_of_LinphonePublishCleared++;break;
default:
break;
}
}
static void subscribe_test_declined(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
......@@ -151,17 +166,68 @@ static void subscribe_test_terminated_by_notifier(void){
subscribe_test_with_args(FALSE);
}
test_t subscribe_tests[] = {
static void publish_test_with_args(bool_t refresh){
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
LinphoneContent content;
LinphoneEvent *lev;
MSList* lcs=ms_list_append(NULL,marie->lc);
lcs=ms_list_append(lcs,pauline->lc);
content.type="application";
content.subtype="somexml";
content.data=(char*)subscribe_content;
content.size=strlen(subscribe_content);
lp_config_set_int(marie->lc->config,"sip","refresh_generic_publish",!refresh);
lev=linphone_core_publish(marie->lc,pauline->identity,"dodo",5,&content);
linphone_event_ref(lev);
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePublishProgress,1,1000));
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePublishOk,1,1000));
if (!refresh){
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePublishExpiring,1,5000));
linphone_event_update_publish(lev,&content);
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePublishProgress,1,1000));
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePublishOk,1,1000));
}else{
}
linphone_event_terminate(lev);
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePublishCleared,1,1000));
linphone_event_unref(lev);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void publish_test(){
publish_test_with_args(TRUE);
}
static void publish_no_auto_test(){
publish_test_with_args(FALSE);
}
test_t event_tests[] = {
{ "Subscribe declined" , subscribe_test_declined },
{ "Subscribe terminated by subscriber", subscribe_test_terminated_by_subscriber },
{ "Subscribe terminated by notifier", subscribe_test_terminated_by_notifier }
{ "Subscribe terminated by notifier", subscribe_test_terminated_by_notifier },
{ "Publish", publish_test },
{ "Publish without automatic refresh",publish_no_auto_test }
};
test_suite_t subscribe_test_suite = {
"Subscribe",
test_suite_t event_test_suite = {
"Event",
NULL,
NULL,
sizeof(subscribe_tests) / sizeof(subscribe_tests[0]),
subscribe_tests
sizeof(event_tests) / sizeof(event_tests[0]),
event_tests
};
......@@ -106,7 +106,7 @@ static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char*
lc = linphone_core_new(v_table,NULL,*filepath!='\0' ? filepath : NULL,NULL);