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); }
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(); } }
public void UpdateState() { RpcAnswer answer = PerformRpcCall(new Combinator("updates.getState")); if (answer.Success) { _updatingState.Update(answer.Combinator); } }
/// <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); } }
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()); }
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()); } }