From 46bdf91b611949c22d78a46e896f71feae25343c Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Sat, 7 Sep 2024 10:01:04 +0300 Subject: [PATCH] Replaced ua_event_handler with new event_handler Added ua_accept and sip_treply API calls Use new 'incoming call` event to prevent auto-sending '180 Ringing' response Send events from C to Java VM on re thread (fixes call recording) --- app/src/main/cpp/baresip.c | 66 ++++++++++++++----- app/src/main/kotlin/com/tutpro/baresip/Api.kt | 3 + .../com/tutpro/baresip/BaresipService.kt | 17 +++-- 3 files changed, 63 insertions(+), 23 deletions(-) diff --git a/app/src/main/cpp/baresip.c b/app/src/main/cpp/baresip.c index f520df39..b74900c7 100644 --- a/app/src/main/cpp/baresip.c +++ b/app/src/main/cpp/baresip.c @@ -145,10 +145,14 @@ static const char *translate_errorcode(uint16_t scode) } } -static void ua_event_handler( - struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) +static void event_handler(enum ua_event ev, struct bevent *event, void *arg) { (void)arg; + const char *prm = bevent_get_text(event); + struct call *call = bevent_get_call(event); + struct ua *ua = bevent_get_ua(event); + const struct sip_msg *msg = bevent_get_msg(event); + struct account *acc = ua_account(bevent_get_ua(event)); const char *tone; char event_buf[256]; enum sdp_dir ardir; @@ -171,6 +175,12 @@ static void ua_event_handler( case UA_EVENT_FALLBACK_FAIL: len = re_snprintf(event_buf, sizeof event_buf, "registering failed,%s", prm); break; + case UA_EVENT_SIPSESS_CONN: + ua = uag_find_msg(msg); + // There is no call yet and call is thus used to hold SIP message + call = (struct call *)msg; + len = re_snprintf(event_buf, sizeof event_buf, "%s,%r", prm, &msg->from.auri); + break; case UA_EVENT_CALL_INCOMING: len = re_snprintf(event_buf, sizeof event_buf, "call incoming,%s", prm); break; @@ -245,16 +255,14 @@ static void ua_event_handler( return; } - re_thread_leave(); - JavaVM *javaVM = g_ctx.javaVM; JNIEnv *env; jint res = (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_6); if (res != JNI_OK) { + LOGW("failed to get javaVM environment, ErrorCode = %d\n", res); res = (*javaVM)->AttachCurrentThread(javaVM, &env, NULL); if (JNI_OK != res) { LOGE("failed to AttachCurrentThread, ErrorCode = %d\n", res); - re_thread_enter(); return; } } @@ -266,7 +274,6 @@ static void ua_event_handler( (*env)->CallVoidMethod(env, g_ctx.mainActivityObj, methodId, jEvent, (jlong)ua, (jlong)call); (*env)->DeleteLocalRef(env, jEvent); - re_thread_enter(); } static void message_handler( @@ -282,8 +289,6 @@ static void message_handler( return; } - re_thread_leave(); - JavaVM *javaVM = g_ctx.javaVM; JNIEnv *env; jint res = (*javaVM)->GetEnv(javaVM, (void **)&env, JNI_VERSION_1_6); @@ -291,7 +296,6 @@ static void message_handler( res = (*javaVM)->AttachCurrentThread(javaVM, &env, NULL); if (JNI_OK != res) { LOGE("failed to AttachCurrentThread, ErrorCode = %d\n", res); - re_thread_enter(); return; } } @@ -318,7 +322,6 @@ static void message_handler( (*env)->DeleteLocalRef(env, jPeer); (*env)->DeleteLocalRef(env, jMsg); - re_thread_enter(); } static void send_resp_handler(int err, const struct sip_msg *msg, void *arg) @@ -335,8 +338,6 @@ static void send_resp_handler(int err, const struct sip_msg *msg, void *arg) LOGD("send_response_handler received response '%u %s' at %s\n", msg->scode, reason_buf, (char *)arg); - re_thread_leave(); - JavaVM *javaVM = g_ctx.javaVM; JNIEnv *env; jint res = (*javaVM)->GetEnv(javaVM, (void **)&env, JNI_VERSION_1_6); @@ -344,7 +345,6 @@ static void send_resp_handler(int err, const struct sip_msg *msg, void *arg) res = (*javaVM)->AttachCurrentThread(javaVM, &env, NULL); if (JNI_OK != res) { LOGE("failed to AttachCurrentThread, ErrorCode = %d\n", res); - re_thread_enter(); return; } } @@ -357,7 +357,6 @@ static void send_resp_handler(int err, const struct sip_msg *msg, void *arg) (*env)->DeleteLocalRef(env, javaReason); (*env)->DeleteLocalRef(env, javaTime); - re_thread_enter(); } enum @@ -524,10 +523,10 @@ JNIEXPORT void JNICALL Java_com_tutpro_baresip_BaresipService_baresipStart( uag_set_exit_handler(ua_exit_handler, NULL); - err = uag_event_register(ua_event_handler, NULL); + err = bevent_register(event_handler, NULL); if (err) { - LOGE("uag_event_register() failed (%d)\n", err); - strcpy(start_error, "uag_event_register"); + LOGE("bevent_register() failed (%d)\n", err); + strcpy(start_error, "bevent_register"); goto out; } @@ -575,7 +574,7 @@ out: conf_close(); baresip_close(); - uag_event_unregister(ua_event_handler); + bevent_unregister(event_handler); LOGD("unloading modules ..."); mod_close(); @@ -1206,6 +1205,23 @@ JNIEXPORT void JNICALL Java_com_tutpro_baresip_Api_ua_1hangup( (*env)->ReleaseStringUTFChars(env, reason, native_reason); } +JNIEXPORT void JNICALL Java_com_tutpro_baresip_Api_ua_1accept( + JNIEnv *env, jobject obj, jlong ua, jlong msg) +{ + (void)env; + (void)obj; + int err; + char *from_uri; + pl_strdup(&from_uri, &((struct sip_msg *)msg)->from.auri); + LOGD("accepting incoming call for ua %ld from %s\n", (long)ua, from_uri); + mem_deref(from_uri); + re_thread_enter(); + err = ua_accept((struct ua *)ua, (struct sip_msg *)msg); + re_thread_leave(); + if (err) + LOGW("accepting incoming call for ua %ld failed with error %d\n", (long)ua, err); +} + JNIEXPORT jlong JNICALL Java_com_tutpro_baresip_Api_ua_1call_1alloc( JNIEnv *env, jobject obj, jlong ua, jlong xCall, jint vidMode) { @@ -1260,6 +1276,20 @@ JNIEXPORT void JNICALL Java_com_tutpro_baresip_Api_ua_1debug(JNIEnv *env, jobjec ua_debug_log((struct ua *)ua); } +JNIEXPORT void JNICALL Java_com_tutpro_baresip_Api_sip_1treply( + JNIEnv *env, jobject obj, jlong msg, jint code, jstring reason) +{ + (void)obj; + const uint16_t native_code = code; + const char *native_reason = (*env)->GetStringUTFChars(env, reason, 0); + LOGD("replying with %d/%s\n", native_code, native_reason); + re_thread_enter(); + (void)sip_treply(NULL, uag_sip(), (const struct sip_msg *)(struct msg *)msg, + native_code, native_reason); + re_thread_leave(); + (*env)->ReleaseStringUTFChars(env, reason, native_reason); +} + JNIEXPORT void JNICALL Java_com_tutpro_baresip_Api_calls_1mute( JNIEnv *env, jobject obj, jboolean mute) { diff --git a/app/src/main/kotlin/com/tutpro/baresip/Api.kt b/app/src/main/kotlin/com/tutpro/baresip/Api.kt index f766a15a..13655a71 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Api.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Api.kt @@ -71,12 +71,15 @@ object Api { external fun ua_register(uap: Long): Int external fun ua_isregistered(uap: Long): Boolean external fun ua_unregister(uap: Long) + external fun ua_accept(uap: Long, msg: Long) external fun ua_hangup(uap: Long, callp: Long, code: Int, reason: String) external fun ua_call_alloc(uap: Long, xcallp: Long, video: Int): Long external fun ua_answer(uap: Long, callp: Long, video: Int) external fun ua_add_custom_header(uap: Long, name: String, body: String) external fun ua_debug(uap: Long) + external fun sip_treply(msg: Long, code: Int, reason: String) + external fun call_connect(callp: Long, peer_uri: String): Int external fun call_hold(callp: Long, hold: Boolean): Int external fun call_ismuted(callp: Long): Boolean diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index f25556ec..697e3ea3 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -632,7 +632,8 @@ class BaresipService: Service() { Log.d(TAG, "got uaEvent $event/$aor/$callp") val call = Call.ofCallp(callp) - if (call == null && callp != 0L && !setOf("call incoming", "call closed").contains(ev[0])) { + if (call == null && callp != 0L && + !setOf("incoming call", "call incoming", "call closed").contains(ev[0])) { Log.w(TAG, "uaEvent $event did not find call $callp") return } @@ -698,7 +699,7 @@ class BaresipService: Service() { playRingBack() return } - "call incoming" -> { + "incoming call" -> { val peerUri = ev[1] val toastMsg = if (!Utils.checkPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO))) getString(R.string.no_calls) @@ -707,12 +708,12 @@ class BaresipService: Service() { getString(R.string.audio_focus_denied) else if (Call.inCall()) String.format(getString(R.string.call_auto_rejected), - Utils.friendlyUri(this, peerUri, ua.account)) + Utils.friendlyUri(this, peerUri, ua.account)) else "" if (toastMsg != "") { - Log.d(TAG, "Auto-rejecting incoming call $uap/$callp/$peerUri") - Api.ua_hangup(uap, callp, 486, "Busy Here") + Log.d(TAG, "Auto-rejecting incoming call $uap/$peerUri") + Api.sip_treply(callp, 486, "Busy Here") toast(toastMsg) val name = "callwaiting_$toneCountry" val resourceId = applicationContext.resources.getIdentifier( @@ -731,6 +732,12 @@ class BaresipService: Service() { } return } + // callp holds SIP message pointer + Api.ua_accept(uap, callp) + return + } + "call incoming" -> { + val peerUri = ev[1] Log.d(TAG, "Incoming call $uap/$callp/$peerUri") Call(callp, ua, peerUri, "in", "incoming", Utils.dtmfWatcher(callp)).add() if (speakerPhone && !Utils.isSpeakerPhoneOn(am))