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); }
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); } };