mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-22 13:48:09 +00:00
enhance event API to be notified of publish states.
lp-gen-wrappers is in progress
This commit is contained in:
parent
f9e0782528
commit
fed415507f
18 changed files with 693 additions and 57 deletions
|
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
100
coreapi/event.c
100
coreapi/event.c
|
|
@ -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){
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionTerminated);
|
||||
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);
|
||||
|
||||
|
||||
sal_enable_test_features(lc->sal,TRUE);
|
||||
#ifndef ANDROID
|
||||
snprintf(rootcapath, sizeof(rootcapath), "%s/certificates/cacert.pem", path);
|
||||
#else
|
||||
|
|
@ -190,6 +190,7 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f
|
|||
mgr->v_table.info_received=info_message_received;
|
||||
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);
|
||||
reset_counters(&mgr->stat);
|
||||
|
|
@ -311,7 +312,7 @@ void liblinphone_tester_init(void) {
|
|||
#ifdef UPNP
|
||||
add_test_suite(&upnp_test_suite);
|
||||
#endif
|
||||
add_test_suite(&subscribe_test_suite);
|
||||
add_test_suite(&event_test_suite);
|
||||
}
|
||||
|
||||
void liblinphone_tester_uninit(void) {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ extern test_suite_t call_test_suite;
|
|||
extern test_suite_t message_test_suite;
|
||||
extern test_suite_t presence_test_suite;
|
||||
extern test_suite_t upnp_test_suite;
|
||||
extern test_suite_t subscribe_test_suite;
|
||||
extern test_suite_t event_test_suite;
|
||||
|
||||
|
||||
extern int liblinphone_tester_nb_test_suites(void);
|
||||
|
|
@ -164,6 +164,11 @@ typedef struct _stats {
|
|||
int number_of_LinphoneSubscriptionTerminated;
|
||||
int number_of_LinphoneSubscriptionError;
|
||||
|
||||
int number_of_LinphonePublishProgress;
|
||||
int number_of_LinphonePublishOk;
|
||||
int number_of_LinphonePublishExpiring;
|
||||
int number_of_LinphonePublishError;
|
||||
int number_of_LinphonePublishCleared;
|
||||
}stats;
|
||||
|
||||
typedef struct _LinphoneCoreManager {
|
||||
|
|
@ -192,6 +197,7 @@ void info_message_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneI
|
|||
void new_subscribtion_request(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
|
||||
void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username);
|
||||
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);
|
||||
|
||||
LinphoneAddress * create_linphone_address(const char * domain);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ COMMON_CFLAGS=\
|
|||
$(STRICT_OPTIONS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
||||
AM_CXXFLAGS=$(LIBXML2_CFLAGS)
|
||||
|
||||
EXTRA_DIST=xml2lpc_jni.cc lpc2xml_jni.cc
|
||||
|
||||
if BUILD_TOOLS
|
||||
|
|
@ -39,7 +41,7 @@ liblpc2xml_la_LIBADD=\
|
|||
libxml2lpc_la_LDFLAGS=-no-undefined
|
||||
liblpc2xml_la_LDFLAGS=-no-undefined
|
||||
|
||||
bin_PROGRAMS=xml2lpc_test lpc2xml_test
|
||||
bin_PROGRAMS=xml2lpc_test lpc2xml_test lp-gen-wrappers
|
||||
|
||||
xml2lpc_test_SOURCES=\
|
||||
xml2lpc_test.c
|
||||
|
|
@ -55,7 +57,13 @@ xml2lpc_test_LDADD=\
|
|||
lpc2xml_test_CFLAGS=$(COMMON_CFLAGS)
|
||||
lpc2xml_test_LDADD=\
|
||||
$(top_builddir)/coreapi/liblinphone.la \
|
||||
liblpc2xml.la
|
||||
liblpc2xml.la
|
||||
|
||||
lp_gen_wrappers_SOURCES=genwrappers.cc
|
||||
|
||||
lp_gen_wrappers_LDADD= \
|
||||
$(LIBXML2_LIBS)
|
||||
|
||||
endif
|
||||
|
||||
|
||||
|
|
|
|||
356
tools/genwrappers.cc
Normal file
356
tools/genwrappers.cc
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2013 Belledonne Communications SARL
|
||||
Simon Morlat (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.
|
||||
*/
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
|
||||
using namespace::std;
|
||||
|
||||
|
||||
class Type{
|
||||
public:
|
||||
enum BasicType{
|
||||
Integer,
|
||||
String,
|
||||
Klass
|
||||
};
|
||||
static Type *getType(const std::string &tname){
|
||||
if (strstr(tname.c_str(),"char")!=0 && strchr(tname.c_str(),'*')!=0){
|
||||
return &sStringType;
|
||||
}else if (strcmp(tname.c_str(),"int")==0){
|
||||
return &sIntegerType;
|
||||
}else{
|
||||
Type* ret;
|
||||
string tmp=tname;
|
||||
ssize_t pos;
|
||||
|
||||
/*really ugly and slow*/
|
||||
|
||||
pos=tmp.find('*');
|
||||
if (pos!=string::npos)
|
||||
tmp.erase(pos,1);
|
||||
|
||||
pos=tmp.find("const");
|
||||
if (pos!=string::npos)
|
||||
tmp.erase(pos,strlen("const"));
|
||||
|
||||
while ((pos=tmp.find(' '))!=string::npos){
|
||||
tmp.erase(pos,1);
|
||||
}
|
||||
|
||||
if ((ret=mTypes[tmp])==0){
|
||||
cout<<"Adding new class type '"<<tmp<<"'"<<endl;
|
||||
ret=mTypes[tmp]=new Type(Type::Klass,tmp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
cout<<"Unhandled type name"<<tname<<endl;
|
||||
return NULL;
|
||||
}
|
||||
const string &getName()const{
|
||||
return mName;
|
||||
}
|
||||
private:
|
||||
BasicType mBasic;
|
||||
string mName;
|
||||
Type(BasicType basic, const std::string &tname="") : mBasic(basic), mName(tname){
|
||||
}
|
||||
static Type sStringType;
|
||||
static Type sIntegerType;
|
||||
static std::map<string,Type*> mTypes;
|
||||
};
|
||||
|
||||
Type Type::sStringType(Type::String);
|
||||
Type Type::sIntegerType(Type::Integer);
|
||||
std::map<string,Type*> Type::mTypes;
|
||||
|
||||
class Argument{
|
||||
public:
|
||||
Argument(Type *type, const string &argname, bool isConst) : mType(type), mName(argname), mConst(isConst){
|
||||
}
|
||||
Type *getType()const{
|
||||
return mType;
|
||||
}
|
||||
private:
|
||||
bool mConst;
|
||||
Type *mType;
|
||||
string mName;
|
||||
string mHelp;
|
||||
};
|
||||
|
||||
class Method{
|
||||
public:
|
||||
Method(const std::string &uid, Argument* return_arg, const std::string &name, const list<Argument*> &args){
|
||||
mUid=uid;
|
||||
mReturn=return_arg;
|
||||
mName=name;
|
||||
mArgs=args;
|
||||
}
|
||||
void setHelp(const std::string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
private:
|
||||
string mUid;
|
||||
Argument *mReturn;
|
||||
string mName;
|
||||
list<Argument*> mArgs;
|
||||
string mHelp;
|
||||
};
|
||||
|
||||
class Class{
|
||||
public:
|
||||
Class(const std::string &name): mName(name){
|
||||
}
|
||||
void addMethod(Method *method){
|
||||
mMethods.push_back(method);
|
||||
}
|
||||
void setHelp(const std::string &help){
|
||||
mHelp=help;
|
||||
}
|
||||
private:
|
||||
list<Method*> mMethods;
|
||||
string mName;
|
||||
string mHelp;
|
||||
};
|
||||
|
||||
class Project{
|
||||
public:
|
||||
Class *getClass(const std::string &name){
|
||||
Class *ret;
|
||||
if ((ret=mClasses[name])==NULL){
|
||||
ret=mClasses[name]=new Class(name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
map<string,Class*> mClasses;
|
||||
};
|
||||
|
||||
static xmlNode * findChild(xmlNode *a_node, const char *element_name){
|
||||
xmlNode *cur_node;
|
||||
|
||||
for (cur_node = a_node->children; cur_node != NULL ; cur_node = cur_node->next){
|
||||
if (strcmp((const char*)cur_node->name,(const char*)element_name)==0){
|
||||
return cur_node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool isSpace(const char *str){
|
||||
for(;*str!='\0';++str){
|
||||
if (!isspace(*str)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static string findChildContent(xmlNode *a_node, const char *element_name){
|
||||
xmlNode *node=findChild(a_node,element_name);
|
||||
string res;
|
||||
if (node) {
|
||||
xmlChar *text=xmlNodeGetContent(node);
|
||||
if (!isSpace((const char*)text))
|
||||
res=(char*)text;
|
||||
xmlFree(text);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#define nullOrEmpty(p) (p==NULL || *p=='\0')
|
||||
|
||||
static Argument *parseArgument(xmlNode *node){
|
||||
string name=findChildContent(node,"name");
|
||||
|
||||
xmlNode *typenode=findChild(node,"type");
|
||||
|
||||
if (!typenode) {
|
||||
cout<<"Cannot find type from node."<<endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
string tname=findChildContent(typenode,"ref");
|
||||
if (tname.empty()){
|
||||
return NULL;
|
||||
}
|
||||
Type *type=Type::getType(tname);
|
||||
if (type==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return new Argument(type,name,false);
|
||||
}
|
||||
|
||||
static string classNameToPrefix(const std::string &classname){
|
||||
char tmp[classname.size()*2];
|
||||
char *w=tmp;
|
||||
ssize_t i;
|
||||
|
||||
for(i=0;i<classname.size();i++){
|
||||
char p=classname[i];
|
||||
if (isupper(p)){
|
||||
if (i!=0){
|
||||
*w++='_';
|
||||
}
|
||||
*w++=tolower(p);
|
||||
}else *w++=p;
|
||||
}
|
||||
*w++='\0';
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static string makeMethodName(const string & suffix){
|
||||
char tmp[suffix.size()];
|
||||
char *w=tmp;
|
||||
ssize_t i;
|
||||
bool useUpper=false;
|
||||
|
||||
for(i=0;i<suffix.size();i++){
|
||||
char p=suffix[i];
|
||||
|
||||
if (p=='_'){
|
||||
if (i>0)
|
||||
useUpper=true;
|
||||
}else{
|
||||
if (useUpper)
|
||||
*w++=toupper(p);
|
||||
else
|
||||
*w++=p;
|
||||
useUpper=false;
|
||||
}
|
||||
}
|
||||
*w++='\0';
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static string extractMethodName(const string &c_name, const std::string& class_name){
|
||||
string prefix=classNameToPrefix(class_name);
|
||||
if (c_name.find(prefix)==0){
|
||||
return makeMethodName(c_name.substr(prefix.size(),string::npos));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static void parseFunction(Project *proj, xmlNode *node){
|
||||
string name;
|
||||
Argument *first_arg=NULL;
|
||||
xmlNode *cur_node;
|
||||
string className;
|
||||
string methodName;
|
||||
|
||||
for (cur_node = node->children; cur_node != NULL ; cur_node = cur_node->next){
|
||||
if (strcmp((const char*)cur_node->name,"name")==0){
|
||||
xmlChar *content=xmlNodeGetContent(cur_node);
|
||||
name=(const char*)content;
|
||||
xmlFree(content);
|
||||
}else if (strcmp((const char*)cur_node->name,"param")==0){
|
||||
if (first_arg==NULL){
|
||||
first_arg=parseArgument(cur_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!first_arg){
|
||||
cout<<"Could not determine first argument of "<<name<<endl;
|
||||
return;
|
||||
}
|
||||
className=first_arg->getType()->getName();
|
||||
methodName=extractMethodName(name,className);
|
||||
if (!methodName.empty()){
|
||||
cout<<"Found "<<className<<"."<<methodName<<"()"<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void parseMemberDef(Project *proj, xmlNode *node){
|
||||
string brief;
|
||||
string detailed;
|
||||
const xmlChar *kind;
|
||||
|
||||
brief=findChildContent(node,"briefdescription");
|
||||
detailed=findChildContent(node,"detaileddescription");
|
||||
|
||||
if (brief.empty() && detailed.empty())
|
||||
return;
|
||||
|
||||
kind=xmlGetProp(node,(const xmlChar*)"kind");
|
||||
//cout<<"Kind="<<(const char*)kind<<endl;
|
||||
if (kind && xmlStrcmp(kind,(const xmlChar*)"function")==0){
|
||||
parseFunction(proj,node);
|
||||
}
|
||||
}
|
||||
|
||||
static void inspectNode(Project *proj, xmlNode *a_node){
|
||||
xmlNode *cur_node;
|
||||
|
||||
for (cur_node = a_node; cur_node != NULL ; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
//printf("node type: Element, name: %s\n", cur_node->name);
|
||||
if (strcmp((const char*)cur_node->name,"memberdef")==0 ){
|
||||
//cout<<"Found memberdef"<<endl;
|
||||
parseMemberDef(proj,cur_node);
|
||||
}
|
||||
}
|
||||
if (cur_node->children) inspectNode(proj,cur_node->children);
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_file(Project *proj, const char *filename){
|
||||
xmlDoc *doc = NULL;
|
||||
xmlNode *root_element = NULL;
|
||||
|
||||
|
||||
/*parse the file and get the DOM */
|
||||
doc = xmlReadFile(filename, NULL, 0);
|
||||
|
||||
if (doc == NULL) {
|
||||
cerr<<"xmlReadFile failed."<<endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*Get the root element node */
|
||||
root_element = xmlDocGetRootElement(doc);
|
||||
|
||||
inspectNode(proj,root_element);
|
||||
|
||||
/*free the document */
|
||||
xmlFreeDoc(doc);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int i;
|
||||
Project *proj=new Project();
|
||||
|
||||
LIBXML_TEST_VERSION
|
||||
|
||||
for(i=1;i<argc;i++){
|
||||
if (strcmp(argv[i],"--help")==0){
|
||||
fprintf(stderr,"%s: [--help] file1 file2...\nParses xml files generated by doxygen to output wrappers in a specified language.\n",argv[0]);
|
||||
return -1;
|
||||
}else{
|
||||
if (parse_file(proj,argv[i])==-1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue