Beispiel #1
0
        private List <RpcAnswer> ProcessAnswers(Combinator request, IEnumerable <Combinator> response)
        {
            var answers = new List <RpcAnswer>();

            foreach (Combinator combinator in response)
            {
                if (_systemCalls.Contains(combinator.Name))
                {
                    Trace.TraceInformation("#System: {0}", combinator);
                    if (combinator.Name == "bad_server_salt")
                    {
                        _settings.NonceNewNonceXor = combinator.Get <long>("new_server_salt");
                        SaveSettings(_settings);
                        RpcAnswer result = RpcCall(request);
                        answers.Add(result);
                    }
                }
                else if (combinator.Descriptor.type == "Updates")
                {
                    Trace.TraceInformation("#Update: {0}", combinator);
                    ProcessUpdates(combinator);
                }
                else
                {
                    Trace.TraceInformation("#Recieve: {0}", combinator);
                    // todo: проверять тип комбинаторов. Учесть: rpc_error, X, Vector t, etc.
                    answers.Add(new RpcAnswer(combinator));
                }
            }
            return(answers);
        }
Beispiel #2
0
        public RpcAnswer PerformRpcCall(Combinator request, bool reconnect = true)
        {
            if (_connection == null)
            {
                throw new Exception("Client not connected");
            }

            RpcSync.WaitOne();
            try
            {
                if (_connection.Connect(reconnect))
                {
                    _session = new EncryptedMtProtoSession(_settings.AuthKey, _settings.NonceNewNonceXor);
                }

                RpcAnswer answer = RpcCall(request);
                if (answer.Combinator != null)
                {
                    _updatingState.Update(answer.Combinator);
                }

                return(answer);
            }
            finally
            {
                RpcSync.Set();
            }
        }
Beispiel #3
0
        public void UpdateState()
        {
            RpcAnswer answer = PerformRpcCall(new Combinator("updates.getState"));

            if (answer.Success)
            {
                _updatingState.Update(answer.Combinator);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Генерация ключа авторизации
        /// </summary>
        /// <returns></returns>
        private bool GenerateAuthKey(string address, int port)
        {
            using (var connection = new TcpConnection(address, port, _formatter))
            {
                connection.Connect(true);

                var pns = new PlainMtProtoSession(connection);

                _nonce = BigInteger.GenerateRandom(128);
                var       reqpq  = new Combinator("req_pq", _nonce);
                RpcAnswer result = pns.RpcCall(reqpq,
                                               "resPQ nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector long = ResPQ");
                if (!result.Success)
                {
                    throw new Exception(result.Error.ToString());
                }

                Combinator reqDhParams = ProcessPqAnswer(result.Combinator);

                result = pns.RpcCall(reqDhParams,
                                     "server_DH_params_ok nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params",
                                     "server_DH_params_fail nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params");

                if (result.Combinator.Name == "server_DH_params_ok")
                {
                    Combinator serverDhInnerData = ProcessDhParams(result.Combinator);
                    Combinator setClientDhParams = SetClientDhParams(serverDhInnerData);

                    result = pns.RpcCall(setClientDhParams,
                                         "dh_gen_ok nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer",
                                         "dh_gen_retry nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer",
                                         "dh_gen_fail nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer");

                    Thread.Sleep(100);

                    switch (result.Combinator.Name)
                    {
                    case "dh_gen_ok":
                        InitialSalt = CalculateInitialSalt(_newNonce, _serverNonce);

                        // Проверим new_nonce_hash1
                        bool res = CheckNewNonceHash(result.Combinator.Get <BigInteger>("new_nonce_hash1"), 1);

                        return(res);

                    case "dh_gen_retry":     // HACK: ретри не реализован
                    case "dh_gen_fail":
                        return(false);

                    default:
                        return(false);
                    }
                }
                return(false);
            }
        }
Beispiel #5
0
        public bool InitConnection(int apiId, string device, string system, string app, string lang, int layer)
        {
            var combinator = new Combinator("initConnection", apiId, device, system, app, lang
                                            , new Combinator("invokeWithLayer", layer, new Combinator("updates.getState")));

            RpcAnswer answer = PerformRpcCall(combinator);

            if (answer.Success)
            {
                _updatingState.Update(answer.Combinator);
                _authorized = true;
                return(true);
            }
            _authorized = false;

            if (answer.Error.ErrorCode == 401)
            {
                return(false);
            }
            throw new Exception(answer.Error.ToString());
        }
Beispiel #6
0
        private void UpdateDifference()
        {
            // updates.getDifference#5b36855a pts:int date:int = updates.Difference;
            RpcAnswer result = RpcCall(new Combinator("updates.getDifference", _updatingState.Pts, _updatingState.Date, _updatingState.Qts));

            // updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
            // updates.difference#8adb0077 new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
            // updates.differenceSlice#c5e839b4 new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> intermediate_state:updates.State = updates.Difference;
            if (result.Success)
            {
                Combinator c = result.Combinator;
                switch (c.Name)
                {
                case "updates.differenceEmpty":
                    _updatingState.Update(c);
                    return;

                case "updates.difference":
                    _updatingState.Update(c.Get <Combinator>("state"));
                    break;

                case "updates.differenceSlice":
                    _updatingState.Update(c.Get <Combinator>("intermediate_state"));
                    break;

                default:
                    throw new ArgumentOutOfRangeException(c.Name);
                }

                Difference(c.Get <Combinator>("new_messages"));
                Difference(c.Get <Combinator>("other_updates"));
                Difference(c.Get <Combinator>("chats"));
                Difference(c.Get <Combinator>("users"));
            }
            else
            {
                throw new Exception(result.Error.ToString());
            }
        }