From a2561ca88c636154dda9ffdc885d26fa5ffafec5 Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Tue, 31 Mar 2015 15:03:52 +0200 Subject: [PATCH] Add ref counting on LinphoneFriend --- coreapi/friend.c | 33 +++++++++--- coreapi/linphonecore.c | 1 + coreapi/linphonecore_jni.cc | 54 +++++++++++++++++++ coreapi/linphonefriend.h | 17 +++++- coreapi/private.h | 8 ++- .../org/linphone/core/LinphoneCore.java | 6 +++ .../org/linphone/core/LinphoneCoreImpl.java | 7 ++- .../org/linphone/core/LinphoneFriendImpl.java | 12 ++--- 8 files changed, 121 insertions(+), 17 deletions(-) diff --git a/coreapi/friend.c b/coreapi/friend.c index 44a2a6f82..e6c429bee 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -128,7 +128,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ } LinphoneFriend * linphone_friend_new(){ - LinphoneFriend *obj=ms_new0(LinphoneFriend,1); + LinphoneFriend *obj=belle_sip_object_new(LinphoneFriend); obj->pol=LinphoneSPAccept; obj->presence=NULL; obj->subscribe=TRUE; @@ -150,11 +150,11 @@ LinphoneFriend *linphone_friend_new_with_address(const char *addr){ } void linphone_friend_set_user_data(LinphoneFriend *lf, void *data){ - lf->up=data; + lf->user_data=data; } void* linphone_friend_get_user_data(const LinphoneFriend *lf){ - return lf->up; + return lf->user_data; } bool_t linphone_friend_in_list(const LinphoneFriend *lf){ @@ -266,7 +266,7 @@ void linphone_friend_close_subscriptions(LinphoneFriend *lf){ } } -void linphone_friend_destroy(LinphoneFriend *lf){ +static void _linphone_friend_destroy(LinphoneFriend *lf){ if (lf->insub) { sal_op_release(lf->insub); lf->insub=NULL; @@ -278,7 +278,6 @@ void linphone_friend_destroy(LinphoneFriend *lf){ if (lf->presence != NULL) linphone_presence_model_unref(lf->presence); if (lf->uri!=NULL) linphone_address_destroy(lf->uri); if (lf->info!=NULL) buddy_info_free(lf->info); - ms_free(lf); } const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf){ @@ -481,7 +480,7 @@ void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf) if (tmp) ms_free(tmp); return ; } - lc->friends=ms_list_append(lc->friends,lf); + lc->friends=ms_list_append(lc->friends,linphone_friend_ref(lf)); lf->lc=lc; if ( linphone_core_ready(lc)) linphone_friend_apply(lf,lc); else lf->commit=TRUE; @@ -685,3 +684,25 @@ LinphoneCore *linphone_friend_get_core(const LinphoneFriend *fr){ return fr->lc; } +LinphoneFriend *linphone_friend_ref(LinphoneFriend *lf) { + belle_sip_object_ref(lf); + return lf; +} + +void linphone_friend_unref(LinphoneFriend *lf) { + belle_sip_object_unref(lf); +} + +/* DEPRECATED */ +void linphone_friend_destroy(LinphoneFriend *lf) { + linphone_friend_unref(lf); +} + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneFriend); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneFriend, belle_sip_object_t, + (belle_sip_object_destroy_t) _linphone_friend_destroy, + NULL, // clone + NULL, // marshal + FALSE +); \ No newline at end of file diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 70b55a109..b5bfc095f 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1253,6 +1253,7 @@ static void ui_config_read(LinphoneCore *lc) int i; for (i=0;(lf=linphone_friend_new_from_config_file(lc,i))!=NULL;i++){ linphone_core_add_friend(lc,lf); + linphone_friend_unref(lf); } call_logs_read_from_config_file(lc); } diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index b372f393c..1fa0390d6 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -250,6 +250,31 @@ jobject getChatMessage(JNIEnv *env, LinphoneChatMessage *msg){ return jobj; } +jobject getFriend(JNIEnv *env, LinphoneFriend *lfriend, jobject core){ + jobject jobj=0; + + if (lfriend!=NULL){ + jclass friendClass = (jclass)env->FindClass("org/linphone/core/LinphoneFriendImpl"); + jmethodID friendCtrId = env->GetMethodID(friendClass,"", "(J)V"); + + void *up=linphone_friend_get_user_data(lfriend); + + if (up==NULL){ + jobj=env->NewObject(friendClass,friendCtrId,(jlong)lfriend); + linphone_friend_set_user_data(lfriend,(void*)env->NewWeakGlobalRef(jobj)); + linphone_friend_ref(lfriend); + }else{ + jobj=env->NewLocalRef((jobject)up); + if (jobj == NULL){ + jobj=env->NewObject(friendClass,friendCtrId,(jlong)lfriend); + linphone_friend_set_user_data(lfriend,(void*)env->NewWeakGlobalRef(jobj)); + } + } + env->DeleteLocalRef(friendClass); + } + return jobj; +} + jobject getEvent(JNIEnv *env, LinphoneEvent *lev){ if (lev==NULL) return NULL; jobject jev=(jobject)linphone_event_get_user_data(lev); @@ -1810,6 +1835,25 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addFriend(JNIEnv* env ) { linphone_core_add_friend((LinphoneCore*)lc,(LinphoneFriend*)aFriend); } +extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getFriendList(JNIEnv* env + ,jobject thiz + ,jlong lc) { + const MSList* friends = linphone_core_get_friend_list((LinphoneCore*)lc); + int friendsSize = ms_list_size(friends); + jclass cls = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneFriendImpl")); + jobjectArray jFriends = env->NewObjectArray(friendsSize,cls,NULL); + + for (int i = 0; i < friendsSize; i++) { + LinphoneFriend* lfriend = (LinphoneFriend*)friends->data; + jobject jfriend = getFriend(env,lfriend,thiz); + if(jfriend != NULL){ + env->SetObjectArrayElement(jFriends, i, jfriend); + } + } + + env->DeleteGlobalRef(cls); + return jFriends; +} extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPresenceInfo(JNIEnv* env ,jobject thiz ,jlong lc @@ -2838,9 +2882,11 @@ extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNI if (jFriendUri) { const char* friendUri = env->GetStringUTFChars(jFriendUri, NULL); lResult= linphone_friend_new_with_address(friendUri); + linphone_friend_set_user_data(lResult,env->NewWeakGlobalRef(thiz)); env->ReleaseStringUTFChars(jFriendUri, friendUri); } else { lResult = linphone_friend_new(); + linphone_friend_set_user_data(lResult,env->NewWeakGlobalRef(thiz)); } return (jlong)lResult; } @@ -2908,6 +2954,14 @@ extern "C" jstring Java_org_linphone_core_LinphoneFriendImpl_getRefKey(JNIEnv* } +extern "C" void Java_org_linphone_core_LinphoneFriendImpl_finalize(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + LinphoneFriend *friend=(LinphoneFriend*)ptr; + linphone_friend_set_user_data(friend,NULL); + linphone_friend_unref(friend); +} + /* * Class: org_linphone_core_LinphoneFriendImpl * Method: getPresenceModel diff --git a/coreapi/linphonefriend.h b/coreapi/linphonefriend.h index d0c18825d..1a6535fed 100644 --- a/coreapi/linphonefriend.h +++ b/coreapi/linphonefriend.h @@ -135,8 +135,9 @@ LINPHONE_PUBLIC LinphoneFriend *linphone_friend_new_with_address(const char *add #define linphone_friend_new_with_addr linphone_friend_new_with_address /** - * Destructor - * @param lf #LinphoneFriend object + * Destroy a LinphoneFriend. + * @param lf LinphoneFriend object + * @deprecated Use linphone_friend_unref() instead. */ LINPHONE_PUBLIC void linphone_friend_destroy(LinphoneFriend *lf); @@ -393,6 +394,18 @@ LINPHONE_PUBLIC LinphoneFriend *linphone_core_find_friend(const LinphoneCore *lc */ LINPHONE_PUBLIC LinphoneFriend *linphone_core_get_friend_by_ref_key(const LinphoneCore *lc, const char *key); +/** + * Acquire a reference to the linphone friend. + * @param[in] lf LinphoneFriend object + * @return The same LinphoneFriend object +**/ +LINPHONE_PUBLIC LinphoneFriend * linphone_friend_ref(LinphoneFriend *lf); + +/** + * Release a reference to the linphone friend. + * @param[in] lf LinohoneFriend object +**/ +LINPHONE_PUBLIC void linphone_friend_unref(LinphoneFriend *lf); /** * Returns the LinphoneCore object managing this friend, if any. diff --git a/coreapi/private.h b/coreapi/private.h index a2f29632f..7daed803e 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -553,6 +553,8 @@ BELLE_SIP_DECLARE_VPTR(LinphoneChatRoom); struct _LinphoneFriend{ + belle_sip_object_t base; + void *user_data; LinphoneAddress *uri; SalOp *insub; SalOp *outsub; @@ -561,7 +563,6 @@ struct _LinphoneFriend{ struct _LinphoneCore *lc; BuddyInfo *info; char *refkey; - void *up; bool_t subscribe; bool_t subscribe_active; bool_t inc_subscribe_pending; @@ -569,6 +570,8 @@ struct _LinphoneFriend{ bool_t initial_subscribes_sent; /*used to know if initial subscribe message was sent or not*/ }; +BELLE_SIP_DECLARE_VPTR(LinphoneFriend); + typedef struct sip_config { @@ -1081,7 +1084,8 @@ BELLE_SIP_TYPE_ID(LinphoneChatRoom), BELLE_SIP_TYPE_ID(LinphoneContent), BELLE_SIP_TYPE_ID(LinphoneLDAPContactProvider), BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch), -BELLE_SIP_TYPE_ID(LinphoneProxyConfig) +BELLE_SIP_TYPE_ID(LinphoneProxyConfig), +BELLE_SIP_TYPE_ID(LinphoneFriend) BELLE_SIP_DECLARE_TYPES_END diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index 2c4616dd8..33f917b7c 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -889,6 +889,12 @@ public interface LinphoneCore { */ void addFriend(LinphoneFriend lf) throws LinphoneCoreException; + /** + * Get list of LinphoneFriend + * @return LinphoneFriend list + */ + LinphoneFriend[] getFriendList(); + /** * @brief Set my presence status * @param minutes_away how long in away diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 80d007172..2268c6585 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -92,6 +92,7 @@ class LinphoneCoreImpl implements LinphoneCore { private native void setPreviewWindowId(long nativePtr, Object wid); private native void setDeviceRotation(long nativePtr, int rotation); private native void addFriend(long nativePtr,long friend); + private native LinphoneFriend[] getFriendList(long nativePtr); private native void setPresenceInfo(long nativePtr, int minutes_away, String alternative_contact, int status); private native int getPresenceInfo(long nativePtr); private native void setPresenceModel(long nativePtr, long presencePtr); @@ -433,8 +434,12 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void addFriend(LinphoneFriend lf) throws LinphoneCoreException { addFriend(nativePtr,((LinphoneFriendImpl)lf).nativePtr); - } + + public synchronized LinphoneFriend[] getFriendList() { + return getFriendList(nativePtr); + } + @SuppressWarnings("deprecation") public synchronized void setPresenceInfo(int minutes_away, String alternative_contact, OnlineStatus status) { setPresenceInfo(nativePtr,minutes_away,alternative_contact,status.mValue); diff --git a/java/impl/org/linphone/core/LinphoneFriendImpl.java b/java/impl/org/linphone/core/LinphoneFriendImpl.java index 2285f3788..220f5dbca 100644 --- a/java/impl/org/linphone/core/LinphoneFriendImpl.java +++ b/java/impl/org/linphone/core/LinphoneFriendImpl.java @@ -22,6 +22,7 @@ import java.io.Serializable; class LinphoneFriendImpl implements LinphoneFriend, Serializable { protected final long nativePtr; + private native void finalize(long nativePtr); private native long newLinphoneFriend(String friendUri); private native void setAddress(long nativePtr,long friend); private native long getAddress(long nativePtr); @@ -34,24 +35,23 @@ class LinphoneFriendImpl implements LinphoneFriend, Serializable { private native void setPresenceModel(long nativePtr, long presencePtr); private native void edit(long nativePtr); private native void done(long nativePtr); - private native void delete(long ptr); private native Object getCore(long ptr); private native void setRefKey(long nativePtr, String key); private native String getRefKey(long nativePtr); - - boolean ownPtr = false; + protected LinphoneFriendImpl() { nativePtr = newLinphoneFriend(null); - } + } protected LinphoneFriendImpl(String friendUri) { nativePtr = newLinphoneFriend(friendUri); } + protected LinphoneFriendImpl(long aNativePtr) { nativePtr = aNativePtr; - ownPtr=false; + } protected void finalize() throws Throwable { - if (ownPtr) delete(nativePtr); + finalize(nativePtr); } public void setAddress(LinphoneAddress anAddress) { this.setAddress(nativePtr, ((LinphoneAddressImpl)anAddress).nativePtr);