mirror of
https://github.com/danog/libtgvoip.git
synced 2025-01-22 21:11:36 +01:00
Detect when proxy does not support UDP and persist that across calls
This commit is contained in:
parent
a7546d438a
commit
fed3bb73ee
@ -845,6 +845,46 @@ void VoIPController::SetConfig(const Config& cfg){
|
|||||||
UpdateAudioBitrateLimit();
|
UpdateAudioBitrateLimit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoIPController::SetPersistentState(vector<uint8_t> state){
|
||||||
|
using namespace json11;
|
||||||
|
|
||||||
|
if(state.empty())
|
||||||
|
return;
|
||||||
|
string jsonErr;
|
||||||
|
string json=string(state.begin(), state.end());
|
||||||
|
Json _obj=Json::parse(json, jsonErr);
|
||||||
|
if(!jsonErr.empty()){
|
||||||
|
LOGE("Error parsing persistable state: %s", jsonErr.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Json::object obj=_obj.object_items();
|
||||||
|
if(obj.find("proxy")!=obj.end()){
|
||||||
|
Json::object proxy=obj["proxy"].object_items();
|
||||||
|
lastTestedProxyServer=proxy["server"].string_value();
|
||||||
|
proxySupportsUDP=proxy["udp"].bool_value();
|
||||||
|
proxySupportsTCP=proxy["tcp"].bool_value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<uint8_t> VoIPController::GetPersistentState(){
|
||||||
|
using namespace json11;
|
||||||
|
|
||||||
|
Json::object obj=Json::object{
|
||||||
|
{"ver", 1},
|
||||||
|
};
|
||||||
|
if(proxyProtocol==PROXY_SOCKS5){
|
||||||
|
char pbuf[128];
|
||||||
|
snprintf(pbuf, sizeof(pbuf), "%s:%u", proxyAddress.c_str(), proxyPort);
|
||||||
|
obj.insert({"proxy", Json::object{
|
||||||
|
{"server", string(pbuf)},
|
||||||
|
{"udp", proxySupportsUDP},
|
||||||
|
{"tcp", proxySupportsTCP}
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
const char* jstr=Json(obj).dump().c_str();
|
||||||
|
return vector<uint8_t>(jstr, jstr+strlen(jstr));
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Internal intialization
|
#pragma mark - Internal intialization
|
||||||
|
|
||||||
void VoIPController::InitializeTimers(){
|
void VoIPController::InitializeTimers(){
|
||||||
@ -877,8 +917,6 @@ void VoIPController::InitializeTimers(){
|
|||||||
}, 0.1, 0.1);
|
}, 0.1, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
udpConnectivityState=UDP_PING_PENDING;
|
|
||||||
udpPingTimeoutID=messageThread.Post(std::bind(&VoIPController::SendUdpPings, this), 0.0, 0.5);
|
|
||||||
messageThread.Post(std::bind(&VoIPController::SendRelayPings, this), 0.0, 2.0);
|
messageThread.Post(std::bind(&VoIPController::SendRelayPings, this), 0.0, 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1373,6 +1411,14 @@ void VoIPController::InitUDPProxy(){
|
|||||||
delete udpSocket;
|
delete udpSocket;
|
||||||
udpSocket=realUdpSocket;
|
udpSocket=realUdpSocket;
|
||||||
}
|
}
|
||||||
|
char sbuf[128];
|
||||||
|
snprintf(sbuf, sizeof(sbuf), "%s:%u", proxyAddress.c_str(), proxyPort);
|
||||||
|
string proxyHostPort(sbuf);
|
||||||
|
if(proxyHostPort==lastTestedProxyServer && !proxySupportsUDP){
|
||||||
|
LOGI("Proxy does not support UDP - using UDP directly instead");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NetworkSocket* tcp=NetworkSocket::Create(PROTO_TCP);
|
NetworkSocket* tcp=NetworkSocket::Create(PROTO_TCP);
|
||||||
tcp->Connect(resolvedProxyAddress, proxyPort);
|
tcp->Connect(resolvedProxyAddress, proxyPort);
|
||||||
|
|
||||||
@ -1410,12 +1456,11 @@ void VoIPController::InitUDPProxy(){
|
|||||||
if(udpProxy->IsFailed()){
|
if(udpProxy->IsFailed()){
|
||||||
udpProxy->Close();
|
udpProxy->Close();
|
||||||
delete udpProxy;
|
delete udpProxy;
|
||||||
useTCP=true;
|
proxySupportsUDP=false;
|
||||||
useUDP=false;
|
|
||||||
udpConnectivityState=UDP_NOT_AVAILABLE;
|
|
||||||
}else{
|
}else{
|
||||||
udpSocket=udpProxy;
|
udpSocket=udpProxy;
|
||||||
}
|
}
|
||||||
|
ResetUdpAvailability();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoIPController::RunRecvThread(){
|
void VoIPController::RunRecvThread(){
|
||||||
@ -1429,6 +1474,9 @@ void VoIPController::RunRecvThread(){
|
|||||||
SetState(STATE_FAILED);
|
SetState(STATE_FAILED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
udpConnectivityState=UDP_PING_PENDING;
|
||||||
|
udpPingTimeoutID=messageThread.Post(std::bind(&VoIPController::SendUdpPings, this), 0.0, 0.5);
|
||||||
}
|
}
|
||||||
while(runReceiver){
|
while(runReceiver){
|
||||||
|
|
||||||
@ -3144,6 +3192,17 @@ void VoIPController::EvaluateUdpPingResults(){
|
|||||||
else
|
else
|
||||||
avgPongs=0.0;
|
avgPongs=0.0;
|
||||||
LOGI("UDP ping reply count: %.2f", avgPongs);
|
LOGI("UDP ping reply count: %.2f", avgPongs);
|
||||||
|
if(avgPongs==0.0 && proxyProtocol==PROXY_SOCKS5 && udpSocket!=realUdpSocket){
|
||||||
|
LOGI("Proxy does not let UDP through, closing proxy connection and using UDP directly");
|
||||||
|
NetworkSocket* proxySocket=udpSocket;
|
||||||
|
proxySocket->Close();
|
||||||
|
udpSocket=realUdpSocket;
|
||||||
|
selectCanceller->CancelSelect();
|
||||||
|
delete proxySocket;
|
||||||
|
proxySupportsUDP=false;
|
||||||
|
ResetUdpAvailability();
|
||||||
|
return;
|
||||||
|
}
|
||||||
bool configUseTCP=ServerConfig::GetSharedInstance()->GetBoolean("use_tcp", true);
|
bool configUseTCP=ServerConfig::GetSharedInstance()->GetBoolean("use_tcp", true);
|
||||||
if(configUseTCP){
|
if(configUseTCP){
|
||||||
if(avgPongs==0.0 || (udpConnectivityState==UDP_BAD && avgPongs<7.0)){
|
if(avgPongs==0.0 || (udpConnectivityState==UDP_BAD && avgPongs<7.0)){
|
||||||
|
@ -369,6 +369,15 @@ namespace tgvoip{
|
|||||||
static int32_t GetConnectionMaxLayer(){
|
static int32_t GetConnectionMaxLayer(){
|
||||||
return 92;
|
return 92;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Get the persistable state of the library, like proxy capabilities, to save somewhere on the disk. Call this at the end of the call.
|
||||||
|
* Using this will speed up the connection establishment in some cases.
|
||||||
|
*/
|
||||||
|
std::vector<uint8_t> GetPersistentState();
|
||||||
|
/**
|
||||||
|
* Load the persistable state. Call this before starting the call.
|
||||||
|
*/
|
||||||
|
void SetPersistentState(std::vector<uint8_t> state);
|
||||||
|
|
||||||
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
|
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
|
||||||
void SetAudioDataCallbacks(std::function<void(int16_t*, size_t)> input, std::function<void(int16_t*, size_t)> output);
|
void SetAudioDataCallbacks(std::function<void(int16_t*, size_t)> input, std::function<void(int16_t*, size_t)> output);
|
||||||
@ -697,6 +706,11 @@ namespace tgvoip{
|
|||||||
video::VideoRenderer* videoRenderer=NULL;
|
video::VideoRenderer* videoRenderer=NULL;
|
||||||
double firstVideoFrameTime=0.0;
|
double firstVideoFrameTime=0.0;
|
||||||
|
|
||||||
|
/*** persistable state values ***/
|
||||||
|
bool proxySupportsUDP=true;
|
||||||
|
bool proxySupportsTCP=true;
|
||||||
|
std::string lastTestedProxyServer="";
|
||||||
|
|
||||||
/*** server config values ***/
|
/*** server config values ***/
|
||||||
uint32_t maxAudioBitrate;
|
uint32_t maxAudioBitrate;
|
||||||
uint32_t maxAudioBitrateEDGE;
|
uint32_t maxAudioBitrateEDGE;
|
||||||
|
@ -38,6 +38,7 @@ jclass jniUtilitiesClass=NULL;
|
|||||||
|
|
||||||
struct ImplDataAndroid{
|
struct ImplDataAndroid{
|
||||||
jobject javaObject;
|
jobject javaObject;
|
||||||
|
std::string persistentStateFile="";
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TGVOIP_PACKAGE_PATH
|
#ifndef TGVOIP_PACKAGE_PATH
|
||||||
@ -115,9 +116,12 @@ namespace tgvoip {
|
|||||||
|
|
||||||
#pragma mark - VoIPController
|
#pragma mark - VoIPController
|
||||||
|
|
||||||
jlong VoIPController_nativeInit(JNIEnv* env, jobject thiz) {
|
jlong VoIPController_nativeInit(JNIEnv* env, jobject thiz, jstring persistentStateFile) {
|
||||||
ImplDataAndroid* impl=(ImplDataAndroid*) malloc(sizeof(ImplDataAndroid));
|
ImplDataAndroid* impl=new ImplDataAndroid();
|
||||||
impl->javaObject=env->NewGlobalRef(thiz);
|
impl->javaObject=env->NewGlobalRef(thiz);
|
||||||
|
if(persistentStateFile){
|
||||||
|
impl->persistentStateFile=jni::JavaStringToStdString(env, persistentStateFile);
|
||||||
|
}
|
||||||
VoIPController* cntrlr=new VoIPController();
|
VoIPController* cntrlr=new VoIPController();
|
||||||
cntrlr->implData=impl;
|
cntrlr->implData=impl;
|
||||||
VoIPController::Callbacks callbacks;
|
VoIPController::Callbacks callbacks;
|
||||||
@ -127,6 +131,22 @@ namespace tgvoip {
|
|||||||
callbacks.groupCallKeySent=groupCallKeySent;
|
callbacks.groupCallKeySent=groupCallKeySent;
|
||||||
callbacks.upgradeToGroupCallRequested=callUpgradeRequestReceived;
|
callbacks.upgradeToGroupCallRequested=callUpgradeRequestReceived;
|
||||||
cntrlr->SetCallbacks(callbacks);
|
cntrlr->SetCallbacks(callbacks);
|
||||||
|
if(!impl->persistentStateFile.empty()){
|
||||||
|
FILE* f=fopen(impl->persistentStateFile.c_str(), "r");
|
||||||
|
if(f){
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size_t len=static_cast<size_t>(ftell(f));
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
if(len<1024*512 && len>0){
|
||||||
|
char *fbuf=static_cast<char *>(malloc(len));
|
||||||
|
fread(fbuf, 1, len, f);
|
||||||
|
std::vector<uint8_t> state(fbuf, fbuf+len);
|
||||||
|
free(fbuf);
|
||||||
|
cntrlr->SetPersistentState(state);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
return (jlong)(intptr_t)cntrlr;
|
return (jlong)(intptr_t)cntrlr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,9 +216,17 @@ namespace tgvoip {
|
|||||||
VoIPController* ctlr=((VoIPController*)(intptr_t)inst);
|
VoIPController* ctlr=((VoIPController*)(intptr_t)inst);
|
||||||
ImplDataAndroid* impl=(ImplDataAndroid*)ctlr->implData;
|
ImplDataAndroid* impl=(ImplDataAndroid*)ctlr->implData;
|
||||||
ctlr->Stop();
|
ctlr->Stop();
|
||||||
|
std::vector<uint8_t> state=ctlr->GetPersistentState();
|
||||||
delete ctlr;
|
delete ctlr;
|
||||||
env->DeleteGlobalRef(impl->javaObject);
|
env->DeleteGlobalRef(impl->javaObject);
|
||||||
free(impl);
|
if(!impl->persistentStateFile.empty()){
|
||||||
|
FILE* f=fopen(impl->persistentStateFile.c_str(), "w");
|
||||||
|
if(f){
|
||||||
|
fwrite(state.data(), 1, state.size(), f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring VoIPController_nativeGetDebugString(JNIEnv* env, jobject thiz, jlong inst){
|
jstring VoIPController_nativeGetDebugString(JNIEnv* env, jobject thiz, jlong inst){
|
||||||
@ -520,7 +548,7 @@ extern "C" void tgvoipRegisterNatives(JNIEnv* env){
|
|||||||
|
|
||||||
// VoIPController
|
// VoIPController
|
||||||
JNINativeMethod controllerMethods[]={
|
JNINativeMethod controllerMethods[]={
|
||||||
{"nativeInit", "()J", (void*)&tgvoip::VoIPController_nativeInit},
|
{"nativeInit", "(Ljava/lang/String;)J", (void*)&tgvoip::VoIPController_nativeInit},
|
||||||
{"nativeStart", "(J)V", (void*)&tgvoip::VoIPController_nativeStart},
|
{"nativeStart", "(J)V", (void*)&tgvoip::VoIPController_nativeStart},
|
||||||
{"nativeConnect", "(J)V", (void*)&tgvoip::VoIPController_nativeConnect},
|
{"nativeConnect", "(J)V", (void*)&tgvoip::VoIPController_nativeConnect},
|
||||||
{"nativeSetProxy", "(JLjava/lang/String;ILjava/lang/String;Ljava/lang/String;)V", (void*)&tgvoip::VoIPController_nativeSetProxy},
|
{"nativeSetProxy", "(JLjava/lang/String;ILjava/lang/String;Ljava/lang/String;)V", (void*)&tgvoip::VoIPController_nativeSetProxy},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user