| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- #include "TgVoip.h"
- #include "VoIPController.h"
- #include "VoIPServerConfig.h"
- #include <stdarg.h>
- #ifndef TGVOIP_USE_CUSTOM_CRYPTO
- extern "C" {
- #include <openssl/sha.h>
- #include <openssl/aes.h>
- #include <openssl/modes.h>
- #include <openssl/rand.h>
- }
- void tgvoip_openssl_aes_ige_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
- AES_KEY akey;
- AES_set_encrypt_key(key, 32*8, &akey);
- AES_ige_encrypt(in, out, length, &akey, iv, AES_ENCRYPT);
- }
- void tgvoip_openssl_aes_ige_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
- AES_KEY akey;
- AES_set_decrypt_key(key, 32*8, &akey);
- AES_ige_encrypt(in, out, length, &akey, iv, AES_DECRYPT);
- }
- void tgvoip_openssl_rand_bytes(uint8_t* buffer, size_t len){
- RAND_bytes(buffer, len);
- }
- void tgvoip_openssl_sha1(uint8_t* msg, size_t len, uint8_t* output){
- SHA1(msg, len, output);
- }
- void tgvoip_openssl_sha256(uint8_t* msg, size_t len, uint8_t* output){
- SHA256(msg, len, output);
- }
- void tgvoip_openssl_aes_ctr_encrypt(uint8_t* inout, size_t length, uint8_t* key, uint8_t* iv, uint8_t* ecount, uint32_t* num){
- AES_KEY akey;
- AES_set_encrypt_key(key, 32*8, &akey);
- CRYPTO_ctr128_encrypt(inout, inout, length, &akey, iv, ecount, num, (block128_f) AES_encrypt);
- }
- void tgvoip_openssl_aes_cbc_encrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
- AES_KEY akey;
- AES_set_encrypt_key(key, 256, &akey);
- AES_cbc_encrypt(in, out, length, &akey, iv, AES_ENCRYPT);
- }
- void tgvoip_openssl_aes_cbc_decrypt(uint8_t* in, uint8_t* out, size_t length, uint8_t* key, uint8_t* iv){
- AES_KEY akey;
- AES_set_decrypt_key(key, 256, &akey);
- AES_cbc_encrypt(in, out, length, &akey, iv, AES_DECRYPT);
- }
- tgvoip::CryptoFunctions tgvoip::VoIPController::crypto={
- tgvoip_openssl_rand_bytes,
- tgvoip_openssl_sha1,
- tgvoip_openssl_sha256,
- tgvoip_openssl_aes_ige_encrypt,
- tgvoip_openssl_aes_ige_decrypt,
- tgvoip_openssl_aes_ctr_encrypt,
- tgvoip_openssl_aes_cbc_encrypt,
- tgvoip_openssl_aes_cbc_decrypt
- };
- #else
- tgvoip::CryptoFunctions tgvoip::VoIPController::crypto; // set it yourself upon initialization
- #endif
- class TgVoipImpl : public TgVoip {
- private:
- tgvoip::VoIPController *controller_;
- std::function<void(TgVoipState)> onStateUpdated_;
- std::function<void(int)> onSignalBarsUpdated_;
- public:
- TgVoipImpl(
- std::vector<TgVoipEndpoint> const &endpoints,
- TgVoipPersistentState const &persistentState,
- TgVoipProxy const *proxy,
- TgVoipConfig const &config,
- TgVoipEncryptionKey const &encryptionKey,
- TgVoipNetworkType initialNetworkType
- #ifdef TGVOIP_USE_CUSTOM_CRYPTO
- ,
- TgVoipCrypto const &crypto
- #endif
- #ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
- ,
- TgVoipAudioDataCallbacks const &audioDataCallbacks
- #endif
- ) {
- #ifdef TGVOIP_USE_CUSTOM_CRYPTO
- 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;
- #endif
- controller_ = new tgvoip::VoIPController();
- controller_->implData = this;
- #ifdef 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 = nullptr;
- callbacks.groupCallKeySent = nullptr;
- callbacks.signalBarCountChanged = &TgVoipImpl::signalBarsCallback;
- callbacks.upgradeToGroupCallRequested = nullptr;
- controller_->SetCallbacks(callbacks);
- std::vector<tgvoip::Endpoint> mappedEndpoints;
- for (auto endpoint : endpoints) {
- tgvoip::Endpoint::Type mappedType;
- 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(endpoint.host.ipv4);
- tgvoip::IPv6Address addressv6(endpoint.host.ipv6);
- mappedEndpoints.emplace_back(endpoint.endpointId, endpoint.port, address, addressv6, mappedType, endpoint.peerTag);
- }
- int mappedDataSaving;
- 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.enableVolumeControl = config.enableVolumeControl;
- 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() {
- if (controller_) {
- stop();
- }
- }
- void setOnStateUpdated(std::function<void(TgVoipState)> onStateUpdated) override {
- onStateUpdated_ = onStateUpdated;
- }
- void setOnSignalBarsUpdated(std::function<void(int)> onSignalBarsUpdated) override {
- onSignalBarsUpdated_ = onSignalBarsUpdated;
- }
- void setNetworkType(TgVoipNetworkType networkType) override {
- int mappedType;
- 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) override {
- controller_->SetMicMute(muteMicrophone);
- }
- void setAudioOutputGainControlEnabled(bool enabled) override {
- controller_->SetAudioOutputGainControlEnabled(enabled);
- }
- void setEchoCancellationStrength(int strength) override {
- controller_->SetEchoCancellationStrength(strength);
- }
- void setAudioInputDevice(std::string id) override {
- controller_->SetCurrentAudioInput(id);
- }
- void setAudioOutputDevice(std::string id) override {
- controller_->SetCurrentAudioOutput(id);
- }
- void setInputVolume(float level) override {
- controller_->SetInputVolume(level);
- }
- void setOutputVolume(float level) override {
- controller_->SetOutputVolume(level);
- }
- void setAudioOutputDuckingEnabled(bool enabled) override {
- #if defined(__APPLE__) && TARGET_OS_OSX
- controller_->SetAudioOutputDuckingEnabled(enabled);
- #endif // TARGET_OS_OSX
- }
- std::string getLastError() override {
- switch (controller_->GetLastError()) {
- case tgvoip::ERROR_INCOMPATIBLE: return "ERROR_INCOMPATIBLE";
- case tgvoip::ERROR_TIMEOUT: return "ERROR_TIMEOUT";
- case tgvoip::ERROR_AUDIO_IO: return "ERROR_AUDIO_IO";
- case tgvoip::ERROR_PROXY: return "ERROR_PROXY";
- default: return "ERROR_UNKNOWN";
- }
- }
- std::string getDebugInfo() override {
- return controller_->GetDebugString();
- }
- int64_t getPreferredRelayId() override {
- return controller_->GetPreferredRelayID();
- }
- TgVoipTrafficStats getTrafficStats() override {
- tgvoip::VoIPController::TrafficStats stats;
- controller_->GetStats(&stats);
- return {
- .bytesSentWifi = stats.bytesSentWifi,
- .bytesReceivedWifi = stats.bytesRecvdWifi,
- .bytesSentMobile = stats.bytesSentMobile,
- .bytesReceivedMobile = stats.bytesRecvdMobile
- };
- }
- TgVoipPersistentState getPersistentState() override {
- return {controller_->GetPersistentState()};
- }
- TgVoipFinalState stop() override {
- controller_->Stop();
- TgVoipFinalState finalState = {
- .persistentState = getPersistentState(),
- .debugLog = controller_->GetDebugLog(),
- .trafficStats = getTrafficStats(),
- .isRatingSuggested = controller_->NeedRate()
- };
- delete controller_;
- controller_ = nullptr;
- return finalState;
- }
- static void controllerStateCallback(tgvoip::VoIPController *controller, int state) {
- auto *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::Established;
- break;
- case tgvoip::STATE_FAILED:
- mappedState = TgVoipState::Failed;
- break;
- case tgvoip::STATE_RECONNECTING:
- mappedState = TgVoipState::Reconnecting;
- break;
- default:
- mappedState = TgVoipState::Established;
- break;
- }
- self->onStateUpdated_(mappedState);
- }
- }
- static void signalBarsCallback(tgvoip::VoIPController *controller, int signalBars) {
- auto *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(nullptr, 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);
- }
- int TgVoip::getConnectionMaxLayer() {
- return tgvoip::VoIPController::GetConnectionMaxLayer();
- }
- std::string TgVoip::getVersion() {
- return tgvoip::VoIPController::GetVersion();
- }
- std::unique_ptr<TgVoip> TgVoip::makeInstance(
- TgVoipConfig const &config,
- TgVoipPersistentState const &persistentState,
- std::vector<TgVoipEndpoint> const &endpoints,
- TgVoipProxy const *proxy,
- TgVoipNetworkType initialNetworkType,
- TgVoipEncryptionKey const &encryptionKey
- #ifdef TGVOIP_USE_CUSTOM_CRYPTO
- ,
- TgVoipCrypto const &crypto
- #endif
- #ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
- ,
- TgVoipAudioDataCallbacks const &audioDataCallbacks
- #endif
- ) {
- return std::make_unique<TgVoipImpl>(
- endpoints,
- persistentState,
- proxy,
- config,
- encryptionKey,
- initialNetworkType
- #ifdef TGVOIP_USE_CUSTOM_CRYPTO
- ,
- crypto
- #endif
- #ifdef TGVOIP_USE_CALLBACK_AUDIO_IO
- ,
- audioDataCallbacks
- #endif
- );
- }
- TgVoip::~TgVoip() = default;
|