mirror of
https://github.com/danog/libtgvoip.git
synced 2024-11-26 20:24:38 +01:00
Add public interface
This commit is contained in:
parent
1870f7fa6e
commit
77e1f5d27a
332
TgVoip.cpp
Executable file
332
TgVoip.cpp
Executable file
@ -0,0 +1,332 @@
|
||||
#import "TgVoip.h"
|
||||
|
||||
#import "VoIPController.h"
|
||||
#import "VoIPServerConfig.h"
|
||||
|
||||
class TgVoipImpl : public TgVoip {
|
||||
public:
|
||||
tgvoip::VoIPController *controller_;
|
||||
std::function<void(TgVoipState)> onStateUpdated_;
|
||||
std::function<void(int)> onSignalBarsUpdated_;
|
||||
|
||||
TgVoipImpl(
|
||||
TgVoipCrypto const &crypto,
|
||||
std::vector<TgVoipEndpoint> const &endpoints,
|
||||
TgVoipPersistentState const &persistentState,
|
||||
std::unique_ptr<TgVoipProxy> const &proxy,
|
||||
TgVoipConfig const &config,
|
||||
TgVoipEncryptionKey const &encryptionKey,
|
||||
TgVoipNetworkType initialNetworkType
|
||||
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
|
||||
,
|
||||
TgVoipAudioDataCallbacks const &audioDataCallbacks
|
||||
#endif
|
||||
) {
|
||||
tgvoip::VoIPController::crypto.sha1 = crypto.sha1;
|
||||
tgvoip::VoIPController::crypto.sha256 = crypto.sha256;
|
||||
tgvoip::VoIPController::crypto.rand_bytes = crypto.rand_bytes;
|
||||
tgvoip::VoIPController::crypto.aes_ige_encrypt = crypto.aes_ige_encrypt;
|
||||
tgvoip::VoIPController::crypto.aes_ige_decrypt = crypto.aes_ige_decrypt;
|
||||
tgvoip::VoIPController::crypto.aes_ctr_encrypt = crypto.aes_ctr_encrypt;
|
||||
|
||||
controller_ = new tgvoip::VoIPController();
|
||||
controller_->implData = this;
|
||||
|
||||
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
|
||||
controller_->SetAudioDataCallbacks(audioDataCallbacks.input, audioDataCallbacks.output, audioDataCallbacks.preprocessed);
|
||||
#endif
|
||||
|
||||
controller_->SetPersistentState(persistentState.value);
|
||||
|
||||
if (proxy != nullptr) {
|
||||
controller_->SetProxy(tgvoip::PROXY_SOCKS5, proxy->host, proxy->port, proxy->login, proxy->password);
|
||||
}
|
||||
|
||||
auto callbacks = tgvoip::VoIPController::Callbacks();
|
||||
callbacks.connectionStateChanged = &TgVoipImpl::controllerStateCallback;
|
||||
callbacks.groupCallKeyReceived = NULL;
|
||||
callbacks.groupCallKeySent = NULL;
|
||||
callbacks.signalBarCountChanged = &TgVoipImpl::signalBarsCallback;
|
||||
callbacks.upgradeToGroupCallRequested = NULL;
|
||||
controller_->SetCallbacks(callbacks);
|
||||
|
||||
std::vector<tgvoip::Endpoint> mappedEndpoints;
|
||||
for (auto endpoint : endpoints) {
|
||||
bool isIpv6 = false;
|
||||
struct in6_addr addrIpV6;
|
||||
if (inet_pton(AF_INET6, endpoint.host.c_str(), &addrIpV6)) {
|
||||
isIpv6 = true;
|
||||
}
|
||||
|
||||
tgvoip::Endpoint::Type mappedType = tgvoip::Endpoint::Type::UDP_RELAY;
|
||||
switch (endpoint.type) {
|
||||
case TgVoipEndpointType::UdpRelay:
|
||||
mappedType = tgvoip::Endpoint::Type::UDP_RELAY;
|
||||
break;
|
||||
case TgVoipEndpointType::Lan:
|
||||
mappedType = tgvoip::Endpoint::Type::UDP_P2P_LAN;
|
||||
break;
|
||||
case TgVoipEndpointType::Inet:
|
||||
mappedType = tgvoip::Endpoint::Type::UDP_P2P_INET;
|
||||
break;
|
||||
case TgVoipEndpointType::TcpRelay:
|
||||
mappedType = tgvoip::Endpoint::Type::TCP_RELAY;
|
||||
break;
|
||||
default:
|
||||
mappedType = tgvoip::Endpoint::Type::UDP_RELAY;
|
||||
break;
|
||||
}
|
||||
|
||||
tgvoip::IPv4Address address(isIpv6 ? std::string() : endpoint.host);
|
||||
tgvoip::IPv6Address addressv6(isIpv6 ? endpoint.host : std::string());
|
||||
|
||||
mappedEndpoints.push_back(tgvoip::Endpoint(endpoint.endpointId, endpoint.port, address, addressv6, mappedType, endpoint.peerTag));
|
||||
}
|
||||
|
||||
int mappedDataSaving = tgvoip::DATA_SAVING_NEVER;
|
||||
switch (config.dataSaving) {
|
||||
case TgVoipDataSaving::Mobile:
|
||||
mappedDataSaving = tgvoip::DATA_SAVING_MOBILE;
|
||||
break;
|
||||
case TgVoipDataSaving::Always:
|
||||
mappedDataSaving = tgvoip::DATA_SAVING_ALWAYS;
|
||||
break;
|
||||
default:
|
||||
mappedDataSaving = tgvoip::DATA_SAVING_NEVER;
|
||||
break;
|
||||
}
|
||||
|
||||
tgvoip::VoIPController::Config mappedConfig(
|
||||
config.initializationTimeout,
|
||||
config.receiveTimeout,
|
||||
mappedDataSaving,
|
||||
config.enableAEC,
|
||||
config.enableNS,
|
||||
config.enableAGC,
|
||||
config.enableCallUpgrade
|
||||
);
|
||||
mappedConfig.logFilePath = config.logPath;
|
||||
mappedConfig.statsDumpFilePath = "";
|
||||
|
||||
controller_->SetConfig(mappedConfig);
|
||||
|
||||
setNetworkType(initialNetworkType);
|
||||
|
||||
std::vector<uint8_t> encryptionKeyValue = encryptionKey.value;
|
||||
controller_->SetEncryptionKey((char *)(encryptionKeyValue.data()), encryptionKey.isOutgoing);
|
||||
controller_->SetRemoteEndpoints(mappedEndpoints, config.enableP2P, config.maxApiLayer);
|
||||
|
||||
controller_->Start();
|
||||
|
||||
controller_->Connect();
|
||||
}
|
||||
|
||||
~TgVoipImpl() {
|
||||
|
||||
}
|
||||
|
||||
void setOnStateUpdated(std::function<void(TgVoipState)> onStateUpdated) {
|
||||
onStateUpdated_ = onStateUpdated;
|
||||
}
|
||||
|
||||
void setOnSignalBarsUpdated(std::function<void(int)> onSignalBarsUpdated) {
|
||||
onSignalBarsUpdated_ = onSignalBarsUpdated;
|
||||
}
|
||||
|
||||
void setNetworkType(TgVoipNetworkType networkType) {
|
||||
int mappedType = tgvoip::NET_TYPE_UNKNOWN;
|
||||
|
||||
switch (networkType) {
|
||||
case TgVoipNetworkType::Unknown:
|
||||
mappedType = tgvoip::NET_TYPE_UNKNOWN;
|
||||
break;
|
||||
case TgVoipNetworkType::Gprs:
|
||||
mappedType = tgvoip::NET_TYPE_GPRS;
|
||||
break;
|
||||
case TgVoipNetworkType::Edge:
|
||||
mappedType = tgvoip::NET_TYPE_EDGE;
|
||||
break;
|
||||
case TgVoipNetworkType::ThirdGeneration:
|
||||
mappedType = tgvoip::NET_TYPE_3G;
|
||||
break;
|
||||
case TgVoipNetworkType::Hspa:
|
||||
mappedType = tgvoip::NET_TYPE_HSPA;
|
||||
break;
|
||||
case TgVoipNetworkType::Lte:
|
||||
mappedType = tgvoip::NET_TYPE_LTE;
|
||||
break;
|
||||
case TgVoipNetworkType::WiFi:
|
||||
mappedType = tgvoip::NET_TYPE_WIFI;
|
||||
break;
|
||||
case TgVoipNetworkType::Ethernet:
|
||||
mappedType = tgvoip::NET_TYPE_ETHERNET;
|
||||
break;
|
||||
case TgVoipNetworkType::OtherHighSpeed:
|
||||
mappedType = tgvoip::NET_TYPE_OTHER_HIGH_SPEED;
|
||||
break;
|
||||
case TgVoipNetworkType::OtherLowSpeed:
|
||||
mappedType = tgvoip::NET_TYPE_OTHER_LOW_SPEED;
|
||||
break;
|
||||
case TgVoipNetworkType::OtherMobile:
|
||||
mappedType = tgvoip::NET_TYPE_OTHER_MOBILE;
|
||||
break;
|
||||
case TgVoipNetworkType::Dialup:
|
||||
mappedType = tgvoip::NET_TYPE_DIALUP;
|
||||
break;
|
||||
default:
|
||||
mappedType = tgvoip::NET_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
controller_->SetNetworkType(mappedType);
|
||||
}
|
||||
|
||||
void setMuteMicrophone(bool muteMicrophone) {
|
||||
controller_->SetMicMute(muteMicrophone);
|
||||
}
|
||||
|
||||
std::string getVersion() {
|
||||
return controller_->GetVersion();
|
||||
}
|
||||
|
||||
TgVoipPersistentState getPersistentState() {
|
||||
std::vector<uint8_t> persistentStateValue = controller_->GetPersistentState();
|
||||
TgVoipPersistentState persistentState = {
|
||||
.value = persistentStateValue
|
||||
};
|
||||
|
||||
return persistentState;
|
||||
}
|
||||
|
||||
std::string getDebugInfo() {
|
||||
return controller_->GetDebugString();
|
||||
}
|
||||
|
||||
TgVoipFinalState stop() {
|
||||
controller_->Stop();
|
||||
|
||||
auto debugLog = controller_->GetDebugLog();
|
||||
|
||||
tgvoip::VoIPController::TrafficStats stats;
|
||||
controller_->GetStats(&stats);
|
||||
|
||||
TgVoipTrafficStats trafficStats = {
|
||||
.bytesSentWifi = stats.bytesSentWifi,
|
||||
.bytesReceivedWifi = stats.bytesRecvdWifi,
|
||||
.bytesSentMobile = stats.bytesSentMobile,
|
||||
.bytesReceivedMobile = stats.bytesRecvdMobile
|
||||
};
|
||||
|
||||
std::vector<uint8_t> persistentStateValue = controller_->GetPersistentState();
|
||||
TgVoipPersistentState persistentState = {
|
||||
.value = persistentStateValue
|
||||
};
|
||||
|
||||
TgVoipFinalState finalState = {
|
||||
.persistentState = persistentState,
|
||||
.debugLog = debugLog,
|
||||
.trafficStats = trafficStats,
|
||||
.isRatingSuggested = controller_->NeedRate()
|
||||
};
|
||||
|
||||
delete controller_;
|
||||
controller_ = NULL;
|
||||
|
||||
return finalState;
|
||||
}
|
||||
|
||||
static void controllerStateCallback(tgvoip::VoIPController *controller, int state) {
|
||||
TgVoipImpl *self = (TgVoipImpl *)controller->implData;
|
||||
if (self->onStateUpdated_) {
|
||||
TgVoipState mappedState;
|
||||
switch (state) {
|
||||
case tgvoip::STATE_WAIT_INIT:
|
||||
mappedState = TgVoipState::WaitInit;
|
||||
break;
|
||||
case tgvoip::STATE_WAIT_INIT_ACK:
|
||||
mappedState = TgVoipState::WaitInitAck;
|
||||
break;
|
||||
case tgvoip::STATE_ESTABLISHED:
|
||||
mappedState = TgVoipState::Estabilished;
|
||||
break;
|
||||
case tgvoip::STATE_FAILED:
|
||||
mappedState = TgVoipState::Failed;
|
||||
break;
|
||||
case tgvoip::STATE_RECONNECTING:
|
||||
mappedState = TgVoipState::Reconnecting;
|
||||
break;
|
||||
default:
|
||||
mappedState = TgVoipState::Estabilished;
|
||||
break;
|
||||
}
|
||||
|
||||
self->onStateUpdated_(mappedState);
|
||||
}
|
||||
}
|
||||
|
||||
static void signalBarsCallback(tgvoip::VoIPController *controller, int signalBars) {
|
||||
TgVoipImpl *self = (TgVoipImpl *)controller->implData;
|
||||
if (self->onSignalBarsUpdated_) {
|
||||
self->onSignalBarsUpdated_(signalBars);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::function<void(std::string const &)> globalLoggingFunction;
|
||||
|
||||
void __tgvoip_call_tglog(const char *format, ...){
|
||||
va_list vaArgs;
|
||||
va_start(vaArgs, format);
|
||||
|
||||
va_list vaCopy;
|
||||
va_copy(vaCopy, vaArgs);
|
||||
const int length = std::vsnprintf(NULL, 0, format, vaCopy);
|
||||
va_end(vaCopy);
|
||||
|
||||
std::vector<char> zc(length + 1);
|
||||
std::vsnprintf(zc.data(), zc.size(), format, vaArgs);
|
||||
va_end(vaArgs);
|
||||
|
||||
if (globalLoggingFunction != nullptr) {
|
||||
globalLoggingFunction(std::string(zc.data(), zc.size()));
|
||||
}
|
||||
}
|
||||
|
||||
void TgVoip::setLoggingFunction(std::function<void(std::string const &)> loggingFunction) {
|
||||
globalLoggingFunction = loggingFunction;
|
||||
}
|
||||
|
||||
void TgVoip::setGlobalServerConfig(const std::string &serverConfig) {
|
||||
tgvoip::ServerConfig::GetSharedInstance()->Update(serverConfig);
|
||||
}
|
||||
|
||||
TgVoip *TgVoip::makeInstance(
|
||||
TgVoipCrypto const &crypto,
|
||||
TgVoipConfig const &config,
|
||||
TgVoipPersistentState const &persistentState,
|
||||
std::vector<TgVoipEndpoint> const &endpoints,
|
||||
std::unique_ptr<TgVoipProxy> const &proxy,
|
||||
TgVoipNetworkType initialNetworkType,
|
||||
TgVoipEncryptionKey const &encryptionKey
|
||||
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
|
||||
,
|
||||
TgVoipAudioDataCallbacks const &audioDataCallbacks
|
||||
#endif
|
||||
) {
|
||||
return new TgVoipImpl(
|
||||
crypto,
|
||||
endpoints,
|
||||
persistentState,
|
||||
proxy,
|
||||
config,
|
||||
encryptionKey,
|
||||
initialNetworkType
|
||||
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
|
||||
,
|
||||
audioDataCallbacks
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
TgVoip::~TgVoip() {
|
||||
}
|
149
TgVoip.h
Executable file
149
TgVoip.h
Executable file
@ -0,0 +1,149 @@
|
||||
#ifndef __TGVOIP_H
|
||||
#define __TGVOIP_H
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
struct TgVoipProxy {
|
||||
std::string host;
|
||||
uint16_t port;
|
||||
std::string login;
|
||||
std::string password;
|
||||
};
|
||||
|
||||
enum class TgVoipEndpointType {
|
||||
Inet,
|
||||
Lan,
|
||||
UdpRelay,
|
||||
TcpRelay
|
||||
};
|
||||
|
||||
struct TgVoipEndpoint {
|
||||
int64_t endpointId;
|
||||
std::string host;
|
||||
uint16_t port;
|
||||
TgVoipEndpointType type;
|
||||
unsigned char peerTag[16];
|
||||
};
|
||||
|
||||
enum class TgVoipNetworkType {
|
||||
Unknown,
|
||||
Gprs,
|
||||
Edge,
|
||||
ThirdGeneration,
|
||||
Hspa,
|
||||
Lte,
|
||||
WiFi,
|
||||
Ethernet,
|
||||
OtherHighSpeed,
|
||||
OtherLowSpeed,
|
||||
OtherMobile,
|
||||
Dialup
|
||||
};
|
||||
|
||||
enum class TgVoipDataSaving {
|
||||
Never,
|
||||
Mobile,
|
||||
Always
|
||||
};
|
||||
|
||||
struct TgVoipPersistentState {
|
||||
std::vector<uint8_t> value;
|
||||
};
|
||||
|
||||
struct TgVoipCrypto {
|
||||
void (*rand_bytes)(uint8_t* buffer, size_t length);
|
||||
void (*sha1)(uint8_t* msg, size_t length, uint8_t* output);
|
||||
void (*sha256)(uint8_t* msg, size_t length, uint8_t* output);
|
||||
void (*aes_ige_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
||||
void (*aes_ige_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
||||
void (*aes_ctr_encrypt)(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num);
|
||||
void (*aes_cbc_encrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
||||
void (*aes_cbc_decrypt)(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv);
|
||||
};
|
||||
|
||||
struct TgVoipConfig {
|
||||
double initializationTimeout;
|
||||
double receiveTimeout;
|
||||
TgVoipDataSaving dataSaving;
|
||||
bool enableP2P;
|
||||
bool enableAEC;
|
||||
bool enableNS;
|
||||
bool enableAGC;
|
||||
bool enableCallUpgrade;
|
||||
std::string logPath;
|
||||
int maxApiLayer;
|
||||
};
|
||||
|
||||
struct TgVoipEncryptionKey {
|
||||
std::vector<uint8_t> value;
|
||||
bool isOutgoing;
|
||||
};
|
||||
|
||||
enum class TgVoipState {
|
||||
WaitInit,
|
||||
WaitInitAck,
|
||||
Estabilished,
|
||||
Failed,
|
||||
Reconnecting
|
||||
};
|
||||
|
||||
struct TgVoipTrafficStats {
|
||||
uint64_t bytesSentWifi;
|
||||
uint64_t bytesReceivedWifi;
|
||||
uint64_t bytesSentMobile;
|
||||
uint64_t bytesReceivedMobile;
|
||||
};
|
||||
|
||||
struct TgVoipFinalState {
|
||||
TgVoipPersistentState persistentState;
|
||||
std::string debugLog;
|
||||
TgVoipTrafficStats trafficStats;
|
||||
bool isRatingSuggested;
|
||||
};
|
||||
|
||||
struct TgVoipAudioDataCallbacks {
|
||||
std::function<void(int16_t*, size_t)> input;
|
||||
std::function<void(int16_t*, size_t)> output;
|
||||
std::function<void(int16_t*, size_t)> preprocessed;
|
||||
};
|
||||
|
||||
class TgVoip {
|
||||
protected:
|
||||
TgVoip() = default;
|
||||
|
||||
public:
|
||||
static void setLoggingFunction(std::function<void(std::string const &)> loggingFunction);
|
||||
static void setGlobalServerConfig(std::string const &serverConfig);
|
||||
static TgVoip *makeInstance(
|
||||
TgVoipCrypto const &crypto,
|
||||
TgVoipConfig const &config,
|
||||
TgVoipPersistentState const &persistentState,
|
||||
std::vector<TgVoipEndpoint> const &endpoints,
|
||||
std::unique_ptr<TgVoipProxy> const &proxy,
|
||||
TgVoipNetworkType initialNetworkType,
|
||||
TgVoipEncryptionKey const &encryptionKey
|
||||
#if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
|
||||
,
|
||||
TgVoipAudioDataCallbacks const &audioDataCallbacks
|
||||
#endif
|
||||
);
|
||||
|
||||
virtual ~TgVoip();
|
||||
|
||||
virtual void setNetworkType(TgVoipNetworkType networkType) = 0;
|
||||
virtual void setMuteMicrophone(bool muteMicrophone) = 0;
|
||||
|
||||
virtual std::string getVersion() = 0;
|
||||
virtual TgVoipPersistentState getPersistentState() = 0;
|
||||
virtual std::string getDebugInfo() = 0;
|
||||
|
||||
virtual void setOnStateUpdated(std::function<void(TgVoipState)> onStateUpdated) = 0;
|
||||
virtual void setOnSignalBarsUpdated(std::function<void(int)> onSignalBarsUpdated) = 0;
|
||||
|
||||
virtual TgVoipFinalState stop() = 0;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user