/// <inheritdoc /> public async Task WriteAsync(TWritePayloadBaseType payload) { //Serializer the payload first so we can build the header byte[] payloadData = Serializer.Serialize(payload); IPacketHeader header = PacketHeaderFactory.Create(payload, payloadData); //VERY critical we lock here otherwise we could write a header and then another unrelated body could be written inbetween using (await writeSynObj.LockAsync().ConfigureAwait(false)) { //It's important to always write the header first await HeaderReaderWriter.WriteHeaderAsync(header) .ConfigureAwait(false); //Write the outgoing message, it will internally create the header and it will be serialized await DecoratedClient.WriteAsync(payloadData) .ConfigureAwait(false); } }
public async Task <NetworkIncomingMessage <TReadPayloadBaseType> > ReadAsync(CancellationToken token) { IPacketHeader header = null; TReadPayloadBaseType payload = null; using (await readSynObj.LockAsync(token).ConfigureAwait(false)) { //Read the header first header = await HeaderReaderWriter.ReadHeaderAsync(token) .ConfigureAwait(false); //If the header is null it means the socket disconnected if (header == null) { return(null); } //if was canceled the header reading probably returned null anyway if (token.IsCancellationRequested) { return(null); } //We need to read enough bytes to deserialize the payload await ReadAsync(PacketPayloadReadBuffer, 0, header.PayloadSize, token) .ConfigureAwait(false); //TODO: Should we timeout? //If the token was canceled then the buffer isn't filled and we can't make a message if (token.IsCancellationRequested) { return(null); } //WARNING: We must do deserialization inside of the lock otherwise we can encounter a race condition //Deserialize the bytes starting from the begining but ONLY read up to the payload size. We reuse this buffer and it's large //so if we don't specify the length we could end up with an issue. payload = Serializer.Deserialize <TReadPayloadBaseType>(PacketPayloadReadBuffer, 0, header.PayloadSize); } return(new NetworkIncomingMessage <TReadPayloadBaseType>(header, payload)); }