private async Task ReadPackets() { var cancellationToken = cancellationTokenSource.Token; try { var deserializer = new TeraSerializer(new MemoryStream(inputBuffer), configuration); while (!cancellationToken.IsCancellationRequested) { const int headerLength = sizeof(ushort); await stream.ReadExactly(inputBuffer, 0, headerLength, cancellationToken); var packetLength = BitConverter.ToUInt16(inputBuffer, 0); await stream.ReadExactly(inputBuffer, headerLength, packetLength - headerLength, cancellationToken); var packet = deserializer.ReadPacket(); //The following call isn't awaited because listeners that wait on future packets would cause a deadlock. NotifyAsync(packet, cancellationToken); } } //If cancellation is requested, end of stream represents a graceful disconnection. catch (EndOfStreamException) when(cancellationToken.IsCancellationRequested) { } }
/// <summary> /// Initializes a new instance of the <see cref="TeraClient" /> class using the specified configuration. /// </summary> /// <param name="clientConfiguration">The configuration for the <see cref="TeraClient" />.</param> /// <param name="dispatcherConfiguration"> /// The configuration for the <see cref="Lotus.Dispatching.Dispatcher" /> that will /// be used internally to dispatch messages. /// </param> public TeraClient( TeraClientConfiguration clientConfiguration, DispatcherConfiguration dispatcherConfiguration) { configuration = clientConfiguration; serializer = new TeraSerializer(new MemoryStream(outputBuffer), configuration); exceptionHandler = configuration.UnhandledExceptionHandler ?? throw new ArgumentNullException(nameof(configuration.UnhandledExceptionHandler)); dispatcherConfiguration.ModuleTypes.Add(typeof(CoreModule)); Dispatcher = new Dispatcher(dispatcherConfiguration); }