...
 
Commits (5)
......@@ -58,16 +58,17 @@ LinphoneAuthInfo *linphone_auth_info_new_for_algorithm(const char *username, con
if (realm!=NULL && (strlen(realm)>0)) obj->realm=ms_strdup(realm);
if (domain!=NULL && (strlen(domain)>0)) obj->domain=ms_strdup(domain);
if (!algorithm)
if (!algorithm) {
obj->algorithm = ms_strdup("MD5");
return obj;
}
if(algorithm && strcasecmp(algorithm, "MD5") && strcasecmp(algorithm, "SHA-256")){
ms_error("Given algorithm %s is not correct.", algorithm);
return NULL;
}
if(algorithm)
obj->algorithm=ms_strdup(algorithm);
obj->algorithm=ms_strdup(algorithm);
return obj;
}
......@@ -101,6 +102,10 @@ const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i) {
return i->username;
}
const char *linphone_auth_info_get_algorithm(const LinphoneAuthInfo *i) {
return i->algorithm;
}
const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i) {
return linphone_auth_info_get_password(i);
}
......@@ -161,6 +166,24 @@ void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *usernam
if (username && strlen(username) > 0) info->username = ms_strdup(username);
}
void linphone_auth_info_set_algorithm(LinphoneAuthInfo *info, const char *algorithm) {
if (info->algorithm) {
ms_free(info->algorithm);
info->algorithm = NULL;
}
if (!algorithm) {
info->algorithm = ms_strdup("MD5");
return;
}
if(algorithm && strcasecmp(algorithm, "MD5") && strcasecmp(algorithm, "SHA-256")){
ms_error("Given algorithm %s is not correct. Set algorithm failed", algorithm);
return;
}
info->algorithm = ms_strdup(algorithm);
}
void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid) {
if (info->userid) {
ms_free(info->userid);
......
......@@ -238,6 +238,10 @@ LinphoneAuthInfo *linphone_factory_create_auth_info(const LinphoneFactory *facto
return linphone_auth_info_new(username, userid, passwd, ha1, realm, domain);
}
LinphoneAuthInfo *linphone_factory_create_auth_info_2(const LinphoneFactory *factory, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain, const char *algorithm) {
return linphone_auth_info_new_for_algorithm(username, userid, passwd, ha1, realm, domain, algorithm);
}
LinphoneCallCbs * linphone_factory_create_call_cbs(const LinphoneFactory *factory) {
return _linphone_call_cbs_new();
}
......
......@@ -3009,11 +3009,11 @@ extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_pauseRegister(JN
}
//Auth Info
extern "C" jlong Java_org_linphone_core_LinphoneAuthInfoImpl_newLinphoneAuthInfo(JNIEnv* env
, jobject thiz ) {
return (jlong)linphone_auth_info_new(NULL,NULL,NULL,NULL,NULL,NULL);
return (jlong)linphone_auth_info_new_for_algorithm(NULL,NULL,NULL,NULL,NULL,NULL,NULL);
}
extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_delete(JNIEnv* env
, jobject thiz
, jlong ptr) {
......@@ -3078,6 +3078,21 @@ extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getUsername
}
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: getAlgoorithm
* Signature: (J)Ljava/lang/String;
*/
extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getAlgorithm
(JNIEnv *env , jobject, jlong auth_info) {
const char* algorithm = linphone_auth_info_get_algorithm((LinphoneAuthInfo*)auth_info);
if (algorithm) {
return env->NewStringUTF(algorithm);
} else {
return NULL;
}
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: setPassword
......@@ -3126,6 +3141,18 @@ extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setUsername
ReleaseStringUTFChars(env, jusername, username);
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: setAlgorithm
* Signature: (JLjava/lang/String;)V
*/
extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setAlgorithm
(JNIEnv *env, jobject, jlong auth_info, jstring jalgorithm) {
const char* username = GetStringUTFChars(env, jalgorithm);
linphone_auth_info_set_algorithm((LinphoneAuthInfo*)auth_info,algorithm);
ReleaseStringUTFChars(env, jalgorithm, algorithm);
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: setAuthUserId
......
......@@ -109,6 +109,13 @@ LINPHONE_PUBLIC void linphone_auth_info_set_password(LinphoneAuthInfo *info, con
**/
LINPHONE_PUBLIC void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *username);
/**
* Sets the algorithm.
* @param[in] info The #LinphoneAuthInfo object
* @param[in] algorithm The algorithm.
**/
LINPHONE_PUBLIC void linphone_auth_info_set_algorithm(LinphoneAuthInfo *info, const char *algorithm);
/**
* Sets the userid.
* @param[in] info The #LinphoneAuthInfo object
......@@ -174,6 +181,13 @@ LINPHONE_PUBLIC void linphone_auth_info_set_tls_key_path(LinphoneAuthInfo *info,
*/
LINPHONE_PUBLIC const char *linphone_auth_info_get_username(const LinphoneAuthInfo *info);
/**
* Gets the algorithm.
* @param[in] info The #LinphoneAuthInfo object
* @return The algorithm.
*/
LINPHONE_PUBLIC const char *linphone_auth_info_get_algorithm(const LinphoneAuthInfo *info);
/**
* Gets the password.
* @param[in] info The #LinphoneAuthInfo object
......
......@@ -2120,6 +2120,7 @@ LINPHONE_PUBLIC void linphone_core_set_default_proxy_config(LinphoneCore *lc, Li
* @param[in] domain String containing the SIP domain for which this authentication information is valid, if it has to be restricted for a single SIP domain.
* @return #LinphoneAuthInfo with default values set
* @ingroup authentication
* @deprecated use linphone_factory_create_auth_info() instead.
*/
LINPHONE_PUBLIC LinphoneAuthInfo * linphone_core_create_auth_info(LinphoneCore *lc, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain);
......
......@@ -217,6 +217,24 @@ LINPHONE_PUBLIC LinphoneAddress *linphone_factory_create_address(const LinphoneF
*/
LINPHONE_PUBLIC LinphoneAuthInfo *linphone_factory_create_auth_info(const LinphoneFactory *factory, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain);
/**
* Creates a #LinphoneAuthInfo object.
* The object can be created empty, that is with all arguments set to NULL.
* Username, userid, password, realm and domain can be set later using specific methods.
* At the end, username and passwd (or ha1) are required.
* @param factory The #LinphoneFactory singleton.
* @param username The username that needs to be authenticated
* @param userid The userid used for authenticating (use NULL if you don't know what it is)
* @param passwd The password in clear text
* @param ha1 The ha1-encrypted password if password is not given in clear text.
* @param realm The authentication domain (which can be larger than the sip domain. Unfortunately many SIP servers don't use this parameter.
* @param domain The SIP domain for which this authentication information is valid, if it has to be restricted for a single SIP domain.
* @param algorithm The algorithm for encrypting password.
* @return A #LinphoneAuthInfo object. linphone_auth_info_destroy() must be used to destroy it when no longer needed. The #LinphoneCore makes a copy of #LinphoneAuthInfo
* passed through linphone_core_add_auth_info().
*/
LINPHONE_PUBLIC LinphoneAuthInfo *linphone_factory_create_auth_info_2(const LinphoneFactory *factory, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain, const char *algorithm);
/**
* Create a #LinphoneCallCbs object that holds callbacks for events happening on a call.
* @param[in] factory #LinphoneFactory singletion object
......
......@@ -93,6 +93,18 @@ public interface LinphoneAuthInfo {
* @return the domain
*/
String getDomain();
/**
* Sets the algorithm
* @param algorithm
*/
void setAlgorithm(String algorithm);
/**
* Gets the algorithm
* @return the algorithm
*/
String getAlgorithm();
/**
* Clones a current auth info
......
......@@ -70,6 +70,17 @@ abstract public class LinphoneCoreFactory {
* */
abstract public LinphoneAuthInfo createAuthInfo(String username, String userid, String passwd, String ha1, String realm, String domain);
/**
* create {@link LinphoneAuthInfo}
* @param username
* @param userid user id as set in auth header
* @param passwd
* @param ha1
* @param realm
* @param algorithm
* */
abstract public LinphoneAuthInfo createAuthInfo(String username, String userid, String passwd, String ha1, String realm, String domain, String algorithm);
/**
* Create a LinphoneCore object. The LinphoneCore is the root for all liblinphone operations. You need only one per application.
* @param listener listener to receive notifications from the core
......
......@@ -25,9 +25,11 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
private native String getPassword(long ptr);
private native String getRealm(long ptr);
private native String getUsername(long ptr);
private native String getAlgorithm(long ptr);
private native void setPassword(long ptr, String password);
private native void setRealm(long ptr, String realm);
private native void setUsername(long ptr, String username);
private native void setAlgorithm(long ptr, String algorithm);
private native void setUserId(long ptr, String username);
private native void setHa1(long ptr, String ha1);
private native void setDomain(long ptr, String domain);
......@@ -48,6 +50,9 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
this(username, null, password, null, realm, domain);
}
protected LinphoneAuthInfoImpl(String username, String userid, String passwd, String ha1, String realm, String domain) {
this(username, userid, passwd, ha1, realm, domain, null);
}
protected LinphoneAuthInfoImpl(String username, String userid, String passwd, String ha1, String realm, String domain, String algorithm) {
nativePtr = newLinphoneAuthInfo();
this.setUsername(username);
this.setUserId(userid);
......@@ -55,6 +60,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
this.setHa1(ha1);
this.setDomain(domain);
this.setRealm(realm);
this.setAlgorithm(algorithm);
ownPtr = true;
}
protected LinphoneAuthInfoImpl(long aNativePtr) {
......@@ -73,6 +79,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
public String getUsername() {
return getUsername (nativePtr);
}
public String getAlgorithm() { return getAlgorithm (nativePtr); }
public void setPassword(String password) {
setPassword(nativePtr,password);
}
......@@ -82,6 +89,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
public void setUsername(String username) {
setUsername(nativePtr,username);
}
public void setAlgorithm(String algorithm) { setAlgorithm(nativePtr,algorithm); }
@Override
public String getUserId() {
return getUserId(nativePtr);
......@@ -116,7 +124,8 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
getPassword(),
getHa1(),
getRealm(),
getDomain());
getDomain(),
getAlgorithm());
return clone;
}
......
......@@ -186,6 +186,13 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
return new LinphoneAuthInfoImpl(username, userid, passwd, ha1, realm, domain);
}
@Override
public LinphoneAuthInfo createAuthInfo(String username, String userid,
String passwd, String ha1, String realm, String domain,
String algorithm) {
return new LinphoneAuthInfoImpl(username, userid, passwd, ha1, realm, domain, algorithm);
}
@Override
public LinphoneContent createLinphoneContent(String type, String subType,
byte [] data, String encoding) {
......
......@@ -169,7 +169,6 @@ private:
SalMulticastRole getMulticastRole (SalStreamType type);
void joinMulticastGroup (int streamIndex, MediaStream *ms);
int findCryptoIndexFromTag (const SalSrtpCryptoAlgo crypto[], unsigned char tag);
void setDtlsFingerprint (MSMediaStreamSessions *sessions, const SalStreamDescription *sd, const SalStreamDescription *remote);
void setDtlsFingerprintOnAllStreams ();
void setupDtlsParams (MediaStream *ms);
......
......@@ -1141,6 +1141,12 @@ string MediaSessionPrivate::getBindIpForStream (int streamIndex) {
* dual stack socket and multicast don't work well on Mac OS (linux is OK, as usual). */
bindIp = (pc->multicastIp.find_first_of(':') == string::npos) ? "0.0.0.0" : "::0";
}
}else if (bindIp.empty()){
/*If ipv6 is not enabled, for listening to 0.0.0.0. The default behavior of mediastreamer when no IP is passed is to try ::0, and in
* case of failure try 0.0.0.0 . But we don't want this if IPv6 is explicitely disabled.*/
if (!linphone_core_ipv6_enabled(q->getCore()->getCCore())){
bindIp = "0.0.0.0";
}
}
return bindIp;
}
......@@ -1710,14 +1716,6 @@ void MediaSessionPrivate::joinMulticastGroup (int streamIndex, MediaStream *ms)
// -----------------------------------------------------------------------------
int MediaSessionPrivate::findCryptoIndexFromTag (const SalSrtpCryptoAlgo crypto[], unsigned char tag) {
for (int i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
if (crypto[i].tag == tag)
return i;
}
return -1;
}
void MediaSessionPrivate::setDtlsFingerprint (MSMediaStreamSessions *sessions, const SalStreamDescription *sd, const SalStreamDescription *remote) {
if (sal_stream_description_has_dtls(sd)) {
if (sd->dtls_role == SalDtlsRoleInvalid)
......@@ -1881,7 +1879,7 @@ void MediaSessionPrivate::updateCryptoParameters (SalMediaDescription *oldMd, Sa
}
bool MediaSessionPrivate::updateStreamCryptoParameters (const SalStreamDescription *localStreamDesc, SalStreamDescription *oldStream, SalStreamDescription *newStream, MediaStream *ms) {
int cryptoIdx = findCryptoIndexFromTag(localStreamDesc->crypto, static_cast<unsigned char>(newStream->crypto_local_tag));
int cryptoIdx = Sal::findCryptoIndexFromTag(localStreamDesc->crypto, static_cast<unsigned char>(newStream->crypto_local_tag));
if (cryptoIdx >= 0) {
if (localDescChanged & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED)
ms_media_stream_sessions_set_srtp_send_key_b64(&ms->sessions, newStream->crypto[0].algo, localStreamDesc->crypto[cryptoIdx].master_key);
......@@ -2694,7 +2692,7 @@ void MediaSessionPrivate::startAudioStream (CallSession::State targetState, bool
// Valid local tags are > 0
if (sal_stream_description_has_srtp(stream)) {
const SalStreamDescription *localStreamDesc = sal_media_description_find_stream(localDesc, stream->proto, SalAudio);
int cryptoIdx = findCryptoIndexFromTag(localStreamDesc->crypto, static_cast<unsigned char>(stream->crypto_local_tag));
int cryptoIdx = Sal::findCryptoIndexFromTag(localStreamDesc->crypto, static_cast<unsigned char>(stream->crypto_local_tag));
if (cryptoIdx >= 0) {
ms_media_stream_sessions_set_srtp_recv_key_b64(&audioStream->ms.sessions, stream->crypto[0].algo, stream->crypto[0].master_key);
ms_media_stream_sessions_set_srtp_send_key_b64(&audioStream->ms.sessions, stream->crypto[0].algo, localStreamDesc->crypto[cryptoIdx].master_key);
......@@ -2874,7 +2872,7 @@ void MediaSessionPrivate::startTextStream () {
getCurrentParams()->getPrivate()->setUsedRealtimeTextCodec(rtp_profile_get_payload(textProfile, usedPt));
getCurrentParams()->enableRealtimeText(true);
if (sal_stream_description_has_srtp(tstream)) {
int cryptoIdx = findCryptoIndexFromTag(localStreamDesc->crypto, static_cast<unsigned char>(tstream->crypto_local_tag));
int cryptoIdx = Sal::findCryptoIndexFromTag(localStreamDesc->crypto, static_cast<unsigned char>(tstream->crypto_local_tag));
if (cryptoIdx >= 0) {
ms_media_stream_sessions_set_srtp_recv_key_b64(&textStream->ms.sessions, tstream->crypto[0].algo, tstream->crypto[0].master_key);
ms_media_stream_sessions_set_srtp_send_key_b64(&textStream->ms.sessions, tstream->crypto[0].algo, localStreamDesc->crypto[cryptoIdx].master_key);
......@@ -2967,7 +2965,7 @@ void MediaSessionPrivate::startVideoStream (CallSession::State targetState) {
if (isActive) {
if (sal_stream_description_has_srtp(vstream)) {
const SalStreamDescription *localStreamDesc = sal_media_description_find_stream(localDesc, vstream->proto, SalVideo);
int cryptoIdx = findCryptoIndexFromTag(localStreamDesc->crypto, static_cast<unsigned char>(vstream->crypto_local_tag));
int cryptoIdx = Sal::findCryptoIndexFromTag(localStreamDesc->crypto, static_cast<unsigned char>(vstream->crypto_local_tag));
if (cryptoIdx >= 0) {
ms_media_stream_sessions_set_srtp_recv_key_b64(&videoStream->ms.sessions, vstream->crypto[0].algo, vstream->crypto[0].master_key);
ms_media_stream_sessions_set_srtp_send_key_b64(&videoStream->ms.sessions, vstream->crypto[0].algo, localStreamDesc->crypto[cryptoIdx].master_key);
......
......@@ -339,9 +339,13 @@ void SalCallOp::sdpProcess(){
strcpy(mResult->streams[i].rtcp_addr,mRemoteMedia->streams[i].rtcp_addr);
mResult->streams[i].rtcp_port=mRemoteMedia->streams[i].rtcp_port;
if (sal_stream_description_has_srtp(&mResult->streams[i])) {
mResult->streams[i].crypto[0] = mRemoteMedia->streams[i].crypto[0];
}
if (sal_stream_description_has_srtp(&mResult->streams[i])) {
int cryptoIdx = Sal::findCryptoIndexFromTag( mRemoteMedia->streams[i].crypto, static_cast<unsigned char>(mResult->streams[i].crypto[0].tag));
if (cryptoIdx >= 0)
mResult->streams[i].crypto[0] = mRemoteMedia->streams[i].crypto[cryptoIdx];
else
lError() << "Failed to find crypto algo with tag: " << mResult->streams[i].crypto_local_tag << "from resulting description [" << mResult << "]";
}
}
}
}
......
......@@ -823,6 +823,13 @@ belle_sip_response_t* Sal::createResponseFromRequest (belle_sip_request_t* req,
return resp;
}
int Sal::findCryptoIndexFromTag (const SalSrtpCryptoAlgo crypto[], unsigned char tag) {
for (int i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
if (crypto[i].tag == tag)
return i;
}
return -1;
}
......
......@@ -253,6 +253,8 @@ public:
belle_sip_source_t *createTimer (belle_sip_source_func_t func, void *data, unsigned int timeoutValueMs, const std::string &timerName);
void cancelTimer (belle_sip_source_t *timer);
//utils
static int findCryptoIndexFromTag (const SalSrtpCryptoAlgo crypto[], unsigned char tag);
private:
struct SalUuid {
......
......@@ -2665,6 +2665,13 @@ static void srtp_call(void) {
call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyNoFirewall,FALSE);
}
/*
*Purpose of this test is to check that even if caller and callee does not have exactly the same crypto suite configured, the matching crypto suite is used.
*/
static void srtp_call_with_different_crypto_suite(void) {
call_base_with_configfile(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyNoFirewall,FALSE, "laure_tcp_rc", "marie_rc");
}
static void zrtp_call(void) {
call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyNoFirewall,FALSE);
}
......@@ -6542,6 +6549,7 @@ test_t call_tests[] = {
TEST_NO_TAG("Call paused resumed with loss", call_paused_resumed_with_loss),
TEST_NO_TAG("Call paused resumed from callee", call_paused_resumed_from_callee),
TEST_NO_TAG("SRTP call", srtp_call),
TEST_NO_TAG("SRTP call with different crypto suite", srtp_call_with_different_crypto_suite),
TEST_NO_TAG("ZRTP call", zrtp_call),
TEST_NO_TAG("ZRTP silent call", zrtp_silent_call),
TEST_NO_TAG("ZRTP SAS call", zrtp_sas_call),
......
......@@ -4,6 +4,7 @@ sip_tcp_port=-1
sip_tls_port=-1
default_proxy=0
ping_with_options=0
srtp_crypto_suites=AES_256_CM_HMAC_SHA1_80
[auth_info_0]
username=laure
......
......@@ -705,6 +705,7 @@ class GenWrapper(object):
'linphone_factory_create_core',
'linphone_factory_create_core_2',
'linphone_factory_create_core_with_config_2',
'linphone_factory_create_auth_info_2',
'linphone_vcard_get_belcard',
'linphone_core_get_current_vtable',
'linphone_factory_get',
......
......@@ -104,6 +104,11 @@ public {{#isLinphoneFactory}}abstract class{{/isLinphoneFactory}}{{#isNotLinphon
abstract public Core getCore(long ptr);
/**
* Creates a #LinphoneAuthInfo object.
*/
abstract public AuthInfo createAuthInfo(String username, String userid, String passwd, String ha1, String realm, String domain, String algorithm);
{{/isLinphoneFactory}}
{{#isLinphoneCore}}
/**
......@@ -181,6 +186,13 @@ class {{classImplName}} {{#isLinphoneFactory}}extends{{/isLinphoneFactory}}{{#is
return getCore(nativePtr, ptr);
}
private native AuthInfo createAuthInfo2(long nativePtr, String username, String userid, String passwd, String ha1, String realm, String domain, String algorithm);
@Override
synchronized public AuthInfo createAuthInfo(String username, String userid, String passwd, String ha1, String realm, String domain, String algorithm) {
return (AuthInfo)createAuthInfo2(nativePtr, username, userid, passwd, ha1, realm, domain, algorithm);
}
@Override
public LoggingService getLoggingService() {
LoggingService l = new LoggingServiceImpl(0);
......
......@@ -496,6 +496,30 @@ jobject Java_{{jni_package}}CoreImpl_getMediastreamerFactory(JNIEnv *env, jobjec
// Manually wrapped
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extern "C" jobject Java_org_linphone_core_FactoryImpl_createAuthInfo2(JNIEnv *env, jobject thiz, jlong ptr, jstring username, jstring userid, jstring passwd, jstring ha1, jstring realm, jstring domain, jstring algorithm) {
LinphoneFactory *cptr = (LinphoneFactory*)ptr;
cptr = linphone_factory_get();
if (cptr == 0) {
return 0;
}
const char* c_username = GetStringUTFChars(env, username);
const char* c_userid = GetStringUTFChars(env, userid);
const char* c_passwd = GetStringUTFChars(env, passwd);
const char* c_ha1 = GetStringUTFChars(env, ha1);
const char* c_realm = GetStringUTFChars(env, realm);
const char* c_domain = GetStringUTFChars(env, domain);
const char* c_algorithm = GetStringUTFChars(env, algorithm);
jobject jni_result = (jobject)getAuthInfo(env, (LinphoneAuthInfo *)linphone_factory_create_auth_info_2(cptr, c_username, c_userid, c_passwd, c_ha1, c_realm, c_domain, c_algorithm));
ReleaseStringUTFChars(env, username, c_username);
ReleaseStringUTFChars(env, userid, c_userid);
ReleaseStringUTFChars(env, passwd, c_passwd);
ReleaseStringUTFChars(env, ha1, c_ha1);
ReleaseStringUTFChars(env, realm, c_realm);
ReleaseStringUTFChars(env, domain, c_domain);
ReleaseStringUTFChars(env, algorithm, c_algorithm);
return jni_result;
}
void Java_org_linphone_core_CallImpl_setNativeVideoWindowId(JNIEnv *env, jobject thiz, jlong ptr, jobject id) {
LinphoneCall *cptr = (LinphoneCall*)ptr;
jobject oldWindow = (jobject) linphone_call_get_native_video_window_id(cptr);
......