mirror of
https://github.com/danog/libtgvoip.git
synced 2025-01-22 13:01:21 +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();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
void VoIPController::InitializeTimers(){
|
||||
@ -877,8 +917,6 @@ void VoIPController::InitializeTimers(){
|
||||
}, 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);
|
||||
}
|
||||
|
||||
@ -1373,6 +1411,14 @@ void VoIPController::InitUDPProxy(){
|
||||
delete udpSocket;
|
||||
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);
|
||||
tcp->Connect(resolvedProxyAddress, proxyPort);
|
||||
|
||||
@ -1410,12 +1456,11 @@ void VoIPController::InitUDPProxy(){
|
||||
if(udpProxy->IsFailed()){
|
||||
udpProxy->Close();
|
||||
delete udpProxy;
|
||||
useTCP=true;
|
||||
useUDP=false;
|
||||
udpConnectivityState=UDP_NOT_AVAILABLE;
|
||||
proxySupportsUDP=false;
|
||||
}else{
|
||||
udpSocket=udpProxy;
|
||||
}
|
||||
ResetUdpAvailability();
|
||||
}
|
||||
|
||||
void VoIPController::RunRecvThread(){
|
||||
@ -1429,6 +1474,9 @@ void VoIPController::RunRecvThread(){
|
||||
SetState(STATE_FAILED);
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
udpConnectivityState=UDP_PING_PENDING;
|
||||
udpPingTimeoutID=messageThread.Post(std::bind(&VoIPController::SendUdpPings, this), 0.0, 0.5);
|
||||
}
|
||||
while(runReceiver){
|
||||
|
||||
@ -3144,6 +3192,17 @@ void VoIPController::EvaluateUdpPingResults(){
|
||||
else
|
||||
avgPongs=0.0;
|
||||
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);
|
||||
if(configUseTCP){
|
||||
if(avgPongs==0.0 || (udpConnectivityState==UDP_BAD && avgPongs<7.0)){
|
||||
|
@ -369,6 +369,15 @@ namespace tgvoip{
|
||||
static int32_t GetConnectionMaxLayer(){
|
||||
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)
|
||||
void SetAudioDataCallbacks(std::function<void(int16_t*, size_t)> input, std::function<void(int16_t*, size_t)> output);
|
||||
@ -692,10 +701,15 @@ namespace tgvoip{
|
||||
std::function<void(int16_t*, size_t)> audioInputDataCallback;
|
||||
std::function<void(int16_t*, size_t)> audioOutputDataCallback;
|
||||
#endif
|
||||
|
||||
|
||||
video::VideoSource* videoSource=NULL;
|
||||
video::VideoRenderer* videoRenderer=NULL;
|
||||
double firstVideoFrameTime=0.0;
|
||||
|
||||
/*** persistable state values ***/
|
||||
bool proxySupportsUDP=true;
|
||||
bool proxySupportsTCP=true;
|
||||
std::string lastTestedProxyServer="";
|
||||
|
||||
/*** server config values ***/
|
||||
uint32_t maxAudioBitrate;
|
||||
|
@ -38,6 +38,7 @@ jclass jniUtilitiesClass=NULL;
|
||||
|
||||
struct ImplDataAndroid{
|
||||
jobject javaObject;
|
||||
std::string persistentStateFile="";
|
||||
};
|
||||
|
||||
#ifndef TGVOIP_PACKAGE_PATH
|
||||
@ -115,9 +116,12 @@ namespace tgvoip {
|
||||
|
||||
#pragma mark - VoIPController
|
||||
|
||||
jlong VoIPController_nativeInit(JNIEnv* env, jobject thiz) {
|
||||
ImplDataAndroid* impl=(ImplDataAndroid*) malloc(sizeof(ImplDataAndroid));
|
||||
jlong VoIPController_nativeInit(JNIEnv* env, jobject thiz, jstring persistentStateFile) {
|
||||
ImplDataAndroid* impl=new ImplDataAndroid();
|
||||
impl->javaObject=env->NewGlobalRef(thiz);
|
||||
if(persistentStateFile){
|
||||
impl->persistentStateFile=jni::JavaStringToStdString(env, persistentStateFile);
|
||||
}
|
||||
VoIPController* cntrlr=new VoIPController();
|
||||
cntrlr->implData=impl;
|
||||
VoIPController::Callbacks callbacks;
|
||||
@ -127,6 +131,22 @@ namespace tgvoip {
|
||||
callbacks.groupCallKeySent=groupCallKeySent;
|
||||
callbacks.upgradeToGroupCallRequested=callUpgradeRequestReceived;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -196,9 +216,17 @@ namespace tgvoip {
|
||||
VoIPController* ctlr=((VoIPController*)(intptr_t)inst);
|
||||
ImplDataAndroid* impl=(ImplDataAndroid*)ctlr->implData;
|
||||
ctlr->Stop();
|
||||
std::vector<uint8_t> state=ctlr->GetPersistentState();
|
||||
delete ctlr;
|
||||
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){
|
||||
@ -520,7 +548,7 @@ extern "C" void tgvoipRegisterNatives(JNIEnv* env){
|
||||
|
||||
// VoIPController
|
||||
JNINativeMethod controllerMethods[]={
|
||||
{"nativeInit", "()J", (void*)&tgvoip::VoIPController_nativeInit},
|
||||
{"nativeInit", "(Ljava/lang/String;)J", (void*)&tgvoip::VoIPController_nativeInit},
|
||||
{"nativeStart", "(J)V", (void*)&tgvoip::VoIPController_nativeStart},
|
||||
{"nativeConnect", "(J)V", (void*)&tgvoip::VoIPController_nativeConnect},
|
||||
{"nativeSetProxy", "(JLjava/lang/String;ILjava/lang/String;Ljava/lang/String;)V", (void*)&tgvoip::VoIPController_nativeSetProxy},
|
||||
|
Loading…
x
Reference in New Issue
Block a user