Exemple #1
0
        async Task ReceiveLoopImpl()
        {
            while (true)
            {
                var msgBody = await _transport.Receive();

                var msg = TgSystemMessageHandler.ReadMsg(msgBody);
                var ctx = new TgSystemMessageHandlerContext();
                msg.Apply(TgSystemMessageHandler.Handle(ctx));

                ctx.NewSalt.Iter(salt =>
                                 _session.SetWith(x => x.With(salt: salt))
                                 );
                ctx.Ack.Iter(_unconfirmedMsgIds.Push);

                Option <TaskCompletionSource <RpcResult> > CaptureFlow(long id) =>
                _rpcFlow.TryRemove(id, out var flow) ? Some(flow) : None;

                ctx.RpcResults.Iter(res => CaptureFlow(res.Id).Match(
                                        flow => flow.SetResult(res),
                                        () => TgTrace.Trace($"TgTransport: Unexpected RPC result, the message id is {res.Id}")
                                        ));

                ctx.Updates.Iter(Updates.OnNext);
            }
        }
        static void HandleNewSessionCreated(BinaryReader messageReader, TgSystemMessageHandlerContext ctx)
        {
            messageReader.ReadInt32();
            var newSession = NewSession.DeserializeTag(messageReader);

            ctx.NewSalt = newSession.ServerSalt;

            TgTrace.Trace("NewSession: " + newSession);
        }
        static RpcResult HandleBadServerSalt(BinaryReader br, TgSystemMessageHandlerContext ctx)
        {
            br.ReadInt32();
            var msg = BadMsgNotification.ServerSaltTag.DeserializeTag(br);

            ctx.NewSalt = msg.NewServerSalt;

            return(RpcResult.OfFail(msg.BadMsgId, new TgBadSaltException()));
        }
        public static Func <Message, Unit> Handle(TgSystemMessageHandlerContext ctx) => message =>
        {
            var br         = message.Body;
            var msgId      = message.Id;
            var typeNumber = PeekTypeNumber(br);

            switch (typeNumber)
            {
            case GZipPackedTypeNumber:
                return(message.Apply(ReadGZipPacked(br).Apply(Message.WithBody)).Apply(Handle(ctx)));

            case MsgContainerTypeNumber:
                return(ReadContainer(br).Iter(Handle(ctx)));

            case RpcResultTypeNumber:
                ctx.Ack.Add(msgId);
                ctx.RpcResults.Add(HandleRpcResult(br));
                return(unit);

            case BadMsgNotification.Tag.TypeNumber:
                ctx.RpcResults.Add(HandleBadMsgNotification(br));
                return(unit);

            case BadMsgNotification.ServerSaltTag.TypeNumber:
                ctx.RpcResults.Add(HandleBadServerSalt(br, ctx));
                return(unit);

            case Pong.TypeNumber:
                ctx.RpcResults.Add(HandlePong(br));
                return(unit);

            case NewSession.TypeNumber:
                ctx.Ack.Add(msgId);
                HandleNewSessionCreated(br, ctx);
                return(unit);

            case MsgsAck.TypeNumber:
                // var msg = br.Apply(MsgsAck.Deserialize);
                // var ids = msg.MsgIds.Apply(xs => string.Join(", ", xs));
                // TlTrace.Trace("Ack: " + ids);
                return(unit);

            case FutureSalts.TypeNumber:
                return(unit);

            case MsgDetailedInfo.Tag.TypeNumber:
                return(unit);

            case MsgDetailedInfo.NewTag.TypeNumber:
                EnsureTypeNumber(br, typeNumber);
                MsgDetailedInfo.NewTag.DeserializeTag(br).AnswerMsgId.With(ctx.Ack.Add);
                return(unit);


            default:
                EnsureTypeNumber(br, typeNumber);

                UpdatesType.TryDeserialize(typeNumber, br).Match(updates =>
                {
                    ctx.Ack.Add(msgId);
                    // TgTrace.Trace("Updates " + updatesOpt.ToString());
                },
                                                                 () =>
                {
                    TgTrace.Trace("TgSystemMessageHandler: Unhandled msg " + typeNumber.ToString("x8"));
                });

                return(unit);
            }
        };