/* This file is part of Telegram Desktop, the official desktop version of Telegram messaging app, see https://telegram.org Telegram Desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. In addition, as a special exception, the copyright holders give permission to link the code of portions of this program with the OpenSSL library. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once #include "base/weak_unique_ptr.h" #include "base/timer.h" #include "mtproto/sender.h" #include "mtproto/auth_key.h" namespace Media { namespace Audio { class Track; } // namespace Audio } // namespace Media namespace tgvoip { class VoIPController; } // namespace tgvoip namespace Calls { struct DhConfig { int32 version = 0; int32 g = 0; std::vector p; }; class Call : public base::enable_weak_from_this, private MTP::Sender { public: class Delegate { public: virtual DhConfig getDhConfig() const = 0; virtual void callFinished(gsl::not_null call) = 0; virtual void callFailed(gsl::not_null call) = 0; virtual void callRedial(gsl::not_null call) = 0; enum class Sound { Connecting, Busy, Ended, }; virtual void playSound(Sound sound) = 0; }; static constexpr auto kRandomPowerSize = 256; static constexpr auto kSha256Size = 32; enum class Type { Incoming, Outgoing, }; Call(gsl::not_null delegate, gsl::not_null user, Type type); Type type() const { return _type; } gsl::not_null user() const { return _user; } void start(base::const_byte_span random); bool handleUpdate(const MTPPhoneCall &call); enum State { Starting, WaitingInit, WaitingInitAck, Established, Failed, HangingUp, Ended, ExchangingKeys, Waiting, Requesting, WaitingIncoming, Ringing, Busy, }; State state() const { return _state; } base::Observable &stateChanged() { return _stateChanged; } void setMute(bool mute); bool isMute() const { return _mute; } base::Observable &muteChanged() { return _muteChanged; } TimeMs getDurationMs() const; void answer(); void hangup(); void redial(); bool isKeyShaForFingerprintReady() const; std::array getKeyShaForFingerprint() const; QString getDebugLog() const; ~Call(); private: void handleRequestError(const RPCError &error); void handleControllerError(int error); void finish(const MTPPhoneCallDiscardReason &reason); void startOutgoing(); void startIncoming(); void startWaitingTrack(); void generateModExpFirst(base::const_byte_span randomSeed); void handleControllerStateChange(tgvoip::VoIPController *controller, int state); void createAndStartController(const MTPDphoneCall &call); template bool checkCallCommonFields(const T &call); bool checkCallFields(const MTPDphoneCall &call); bool checkCallFields(const MTPDphoneCallAccepted &call); void confirmAcceptedCall(const MTPDphoneCallAccepted &call); void startConfirmedCall(const MTPDphoneCall &call); void setState(State state); void setStateQueued(State state); void setFailedQueued(int error); void destroyController(); gsl::not_null _delegate; gsl::not_null _user; Type _type = Type::Outgoing; State _state = State::Starting; bool _finishAfterRequestingCall = false; base::Observable _stateChanged; TimeMs _startTime = 0; base::DelayedCallTimer _finishByTimeoutTimer; base::Timer _discardByTimeoutTimer; bool _mute = false; base::Observable _muteChanged; DhConfig _dhConfig; std::vector _ga; std::vector _gb; std::array _gaHash; std::array _randomPower; MTP::AuthKey::Data _authKey; MTPPhoneCallProtocol _protocol; uint64 _id = 0; uint64 _accessHash = 0; uint64 _keyFingerprint = 0; std::unique_ptr _controller; std::unique_ptr _waitingTrack; }; void UpdateConfig(const std::map &data); } // namespace Calls