Esempio n. 1
0
        /// <summary>Sends a <see cref="SPDYFrame"/> on the network.</summary>
        /// <exception cref="InvalidOperationException">Thrown if the connection was closed (<see cref="IsOpen"/> is false) or if the
        /// connection becomes closed while sending the frame
        /// </exception>
        /// <remarks>Only one thread is allowed to be sending frames at a time. If the <paramref name="cancelToken"/> is canceled in the
        /// middle of sending the frame, the connection may be closed.
        /// </remarks>
        public async Task SendFrameAsync(SPDYFrame frame, CancellationToken cancelToken = default)
        {
            if (!frame.IsValid)
            {
                throw new ArgumentException("The frame is not valid.");
            }
            AssertOpen();
            cancelToken.ThrowIfCancellationRequested();
            frame.CopyHeaderTo(writeBuffer);             // get the header bytes
            try
            {
                await writeStream.WriteAsync(writeBuffer, 0, SPDYFrame.HeaderSize, cancelToken).ConfigureAwait(false); // send the header

                await writeStream.WriteAsync(frame.Data, 0, frame.DataLength, cancelToken).ConfigureAwait(false);      // and then the data
            }
            catch (Exception ex)                                                                                       // if an exception occurred, we don't know if the state of the stream has been corrupted
            {
                CloseCore();                                                                                           // so stay on the safe side and close the connection
                if (ex is ObjectDisposedException || ex is IOException || ex is System.Net.Sockets.SocketException)    // if the connection was closed...
                {
                    throw new InvalidOperationException("The connection was closed.", ex);                             // normalize to a known exception
                }
                throw;                                                                                                 // for other exceptions (e.g. cancellation), rethrow
            }
        }