public static void _Tests(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cQuotedPrintableDecoder), nameof(_Tests)); if (LTest("testNow's the time = \r\n", "for all folk to come=\t \t \r\n", " to the aid of their country. \t\r\n") != "Now's the time for all folk to come to the aid of their country.\r\n") { throw new cTestsException($"{nameof(cQuotedPrintableDecoder)}.1"); } string LTest(params string[] pLines) { var lMC = new cMethodControl(-1, System.Threading.CancellationToken.None); var lWriteSizer = new cBatchSizer(new cBatchSizerConfiguration(1, 10, 1000, 1)); using (var lStream = new MemoryStream()) { cDecoder lDecoder = new cQuotedPrintableDecoder(lStream); int lOffset = 4; foreach (var lLine in pLines) { lDecoder.WriteAsync(lMC, new cBytes(lLine), lOffset, lWriteSizer, lContext).Wait(); lOffset = 0; } lDecoder.FlushAsync(lMC, lWriteSizer, lContext).Wait(); return(new string(System.Text.Encoding.UTF8.GetChars(lStream.GetBuffer(), 0, (int)lStream.Length))); } } }
public async sealed override Task FlushAsync(cMethodControl pMC, cBatchSizer pWriteSizer, cTrace.cContext pContext) { if (mBufferedCR) { mLine.Add(cASCII.CR); } await YWriteLineAsync(pMC, mLine, pWriteSizer, pContext).ConfigureAwait(false); await YFlushAsync(pMC, pWriteSizer, pContext).ConfigureAwait(false); }
private async Task ZUIDFetchBodyAsync(iMailboxHandle pMailboxHandle, cUID pUID, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cBodyFetchConfiguration pConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZUIDFetchBodyAsync), pMailboxHandle, pUID, pSection, pDecoding); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || lSession.ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pMailboxHandle == null) { throw new ArgumentNullException(nameof(pMailboxHandle)); } if (pUID == null) { throw new ArgumentNullException(nameof(pUID)); } if (pSection == null) { throw new ArgumentNullException(nameof(pSection)); } if (pStream == null) { throw new ArgumentNullException(nameof(pStream)); } if (!pStream.CanWrite) { throw new ArgumentOutOfRangeException(nameof(pStream)); } if (pConfiguration == null) { using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); var lProgress = new cProgress(); var lWriteSizer = new cBatchSizer(mFetchBodyWriteConfiguration); await lSession.UIDFetchBodyAsync(lMC, pMailboxHandle, pUID, pSection, pDecoding, pStream, lProgress, lWriteSizer, lContext).ConfigureAwait(false); } } else { var lMC = new cMethodControl(pConfiguration.Timeout, pConfiguration.CancellationToken); var lProgress = new cProgress(mSynchroniser, pConfiguration.Increment); var lWriteSizer = new cBatchSizer(pConfiguration.Write ?? mFetchBodyWriteConfiguration); await lSession.UIDFetchBodyAsync(lMC, pMailboxHandle, pUID, pSection, pDecoding, pStream, lProgress, lWriteSizer, lContext).ConfigureAwait(false); } }
public void SetFetchBodyReadConfiguration(cBatchSizerConfiguration pConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(SetFetchBodyReadConfiguration), pConfiguration); if (pConfiguration == null) { throw new ArgumentNullException(nameof(pConfiguration)); } mFetchBodyReadSizer = new cBatchSizer(pConfiguration); }
protected async Task YFlushAsync(cMethodControl pMC, cBatchSizer pWriteSizer, cTrace.cContext pContext) { if (mCount == 0) { return; } pContext.TraceVerbose("writing {0} bytes to stream", mCount); mStopwatch.Restart(); await mStream.WriteAsync(mBuffer, 0, mCount, pMC.CancellationToken).ConfigureAwait(false); mStopwatch.Stop(); // store the time taken so the next write is a better size pWriteSizer.AddSample(mCount, mStopwatch.ElapsedMilliseconds); mCount = 0; }
// (note for when adding more: they need to be disposed) public cSession(cCallbackSynchroniser pSynchroniser, fCapabilities pIgnoreCapabilities, fMailboxCacheDataItems pMailboxCacheDataItems, cBatchSizerConfiguration pNetworkWriteConfiguration, cIdleConfiguration pIdleConfiguration, cBatchSizerConfiguration pFetchCacheItemsConfiguration, cBatchSizerConfiguration pFetchBodyReadConfiguration, Encoding pEncoding, cTrace.cContext pParentContext) { var lContext = pParentContext.NewObject(nameof(cSession), pIgnoreCapabilities, pMailboxCacheDataItems, pNetworkWriteConfiguration, pIdleConfiguration, pFetchCacheItemsConfiguration, pFetchBodyReadConfiguration); mSynchroniser = pSynchroniser ?? throw new ArgumentNullException(nameof(pSynchroniser)); mIgnoreCapabilities = pIgnoreCapabilities; mMailboxCacheDataItems = pMailboxCacheDataItems; mPipeline = new cCommandPipeline(pSynchroniser, ZDisconnected, pNetworkWriteConfiguration, pIdleConfiguration, lContext); mFetchCacheItemsSizer = new cBatchSizer(pFetchCacheItemsConfiguration); mFetchBodyReadSizer = new cBatchSizer(pFetchBodyReadConfiguration); mCommandPartFactory = new cCommandPartFactory(false, null); if (pEncoding == null) { mEncodingPartFactory = mCommandPartFactory; } else { mEncodingPartFactory = new cCommandPartFactory(false, pEncoding); } }
public override Task WriteAsync(cMethodControl pMC, cBytes pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext) => YWriteAsync(pMC, pBytes, pOffset, pWriteSizer, pContext);
private async Task ZBackgroundSendAppendDataAndMoveNextAsync(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(ZBackgroundSendAppendDataAndMoveNextAsync)); switch (mCurrentCommand.CurrentPart()) { case cTextCommandPart lText: await ZBackgroundSendAppendDataAsync(lText.Secret, lText.Bytes, lText.Bytes.Count, lContext).ConfigureAwait(false); break; case cLiteralCommandPart lLiteral: await ZBackgroundSendAppendDataAsync(lLiteral.Secret, lLiteral.Bytes, lLiteral.Bytes.Count, lContext).ConfigureAwait(false); break; case cStreamCommandPart lStream: int lBytesRemaining = lStream.Length; if (lBytesRemaining > 0) { Stopwatch lStopwatch = new Stopwatch(); cBatchSizer lReadSizer = new cBatchSizer(lStream.ReadConfiguration); byte[] lBuffer = new byte[lReadSizer.Current]; while (lBytesRemaining > 0) { int lReadSize = Math.Min(lReadSizer.Current, lBytesRemaining); if (lReadSize > lBuffer.Length) { lBuffer = new byte[lReadSize]; } if (!lStream.Secret) { lContext.TraceVerbose("reading {0} bytes from stream", lReadSize); } lStopwatch.Restart(); int lCount = await lStream.Stream.ReadAsync(lBuffer, 0, lReadSize, mBackgroundCancellationTokenSource.Token).ConfigureAwait(false); lStopwatch.Stop(); // store the time taken so the next read is a better size lReadSizer.AddSample(lCount, lStopwatch.ElapsedMilliseconds); await ZBackgroundSendAppendDataAsync(lStream.Secret, lBuffer, lCount, lContext).ConfigureAwait(false); lBytesRemaining -= lCount; } } break; default: throw new cInternalErrorException(); } if (mCurrentCommand.MoveNext()) { return; } ZBackgroundSendTerminateCommand(lContext); }
public cConnection(cBatchSizerConfiguration pWriteConfiguration) { mWriteSizer = new cBatchSizer(pWriteConfiguration); }
private async Task ZFetchBodyAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, iMessageHandle pMessageHandle, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cProgress pProgress, cBatchSizer pWriteSizer, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZFetchBodyAsync), pMC, pMailboxHandle, pUID, pMessageHandle, pSection, pDecoding); if (pSection == null) { throw new ArgumentNullException(nameof(pSection)); } if (pStream == null) { throw new ArgumentNullException(nameof(pStream)); } if (pProgress == null) { throw new ArgumentNullException(nameof(pProgress)); } if (pWriteSizer == null) { throw new ArgumentNullException(nameof(pWriteSizer)); } if (!pStream.CanWrite) { throw new ArgumentOutOfRangeException(nameof(pStream)); } // work out if binary can/should be used or not bool lBinary = _Capabilities.Binary && pSection.TextPart == eSectionTextPart.all && pDecoding != eDecodingRequired.none; cDecoder lDecoder; if (lBinary || pDecoding == eDecodingRequired.none) { lDecoder = new cIdentityDecoder(pStream); } else if (pDecoding == eDecodingRequired.base64) { lDecoder = new cBase64Decoder(pStream); } else if (pDecoding == eDecodingRequired.quotedprintable) { lDecoder = new cQuotedPrintableDecoder(pStream); } else { throw new cContentTransferDecodingException("required decoding not supported", lContext); } uint lOrigin = 0; Stopwatch lStopwatch = new Stopwatch(); while (true) { int lLength = mFetchBodyReadSizer.Current; lStopwatch.Restart(); cBody lBody; if (pUID == null) { lBody = await ZFetchBodyAsync(pMC, pMessageHandle, lBinary, pSection, lOrigin, (uint)lLength, lContext).ConfigureAwait(false); } else { lBody = await ZUIDFetchBodyAsync(pMC, pMailboxHandle, pUID, lBinary, pSection, lOrigin, (uint)lLength, lContext).ConfigureAwait(false); } lStopwatch.Stop(); // store the time taken so the next fetch is a better size mFetchBodyReadSizer.AddSample(lBody.Bytes.Count, lStopwatch.ElapsedMilliseconds); uint lBodyOrigin = lBody.Origin ?? 0; // the body that we get may start before the place that we asked for int lOffset = (int)(lOrigin - lBodyOrigin); // write the bytes await lDecoder.WriteAsync(pMC, lBody.Bytes, lOffset, pWriteSizer, lContext).ConfigureAwait(false); // update progress pProgress.Increment(lBody.Bytes.Count - lOffset, lContext); // if the body we got was the whole body, we are done if (lBody.Origin == null) { break; } // if we got less bytes than asked for then we will assume that we are at the end if (lBody.Bytes.Count - lOffset < lLength) { break; } // set the start point for the next fetch lOrigin = lBodyOrigin + (uint)lBody.Bytes.Count; } await lDecoder.FlushAsync(pMC, pWriteSizer, lContext).ConfigureAwait(false); }
public Task UIDFetchBodyAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cProgress pProgress, cBatchSizer pWriteSizer, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(UIDFetchBodyAsync), pMC, pMailboxHandle, pUID, pSection, pDecoding); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUID.UIDValidity); // to be repeated inside the select lock return(ZFetchBodyAsync(pMC, pMailboxHandle, pUID, null, pSection, pDecoding, pStream, pProgress, pWriteSizer, lContext)); }
public async sealed override Task WriteAsync(cMethodControl pMC, cBytes pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext) { while (pOffset < pBytes.Count) { byte lByte = pBytes[pOffset++]; if (mBufferedCR) { mBufferedCR = false; if (lByte == cASCII.LF) { await YWriteLineAsync(pMC, mLine, pWriteSizer, pContext).ConfigureAwait(false); mLine.Clear(); continue; } mLine.Add(cASCII.CR); } if (lByte == cASCII.CR) { mBufferedCR = true; } else { mLine.Add(lByte); } } }
public override Task FlushAsync(cMethodControl pMC, cBatchSizer pWriteSizer, cTrace.cContext pContext) => YFlushAsync(pMC, pWriteSizer, pContext);
protected abstract Task YWriteLineAsync(cMethodControl pMC, List <byte> pLine, cBatchSizer pWriteSizer, cTrace.cContext pContext);
public abstract Task FlushAsync(cMethodControl pMC, cBatchSizer pWriteSizer, cTrace.cContext pContext);
public abstract Task WriteAsync(cMethodControl pMC, cBytes pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext);
protected async override Task YWriteLineAsync(cMethodControl pMC, List <byte> pLine, cBatchSizer pWriteSizer, cTrace.cContext pContext) { // build the buffer to decode mBytes.Clear(); foreach (var lByte in pLine) { if (cBase64.IsInAlphabet(lByte)) { mBytes.Add(lByte); } } // special case if (mBytes.Count == 0) { return; } // decode if (!cBase64.TryDecode(mBytes, out var lBytes, out var lError)) { throw new cContentTransferDecodingException(lError, pContext); } await YWriteAsync(pMC, lBytes, 0, pWriteSizer, pContext).ConfigureAwait(false); }
protected async Task YWriteAsync(cMethodControl pMC, IList <byte> pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext) { if (mStream.CanTimeout) { mStream.WriteTimeout = pMC.Timeout; } while (pOffset < pBytes.Count) { if (mCount == 0) { mBuffer = new byte[pWriteSizer.Current]; } while (mCount < mBuffer.Length && pOffset < pBytes.Count) { mBuffer[mCount++] = pBytes[pOffset++]; } if (mCount < mBuffer.Length) { return; } await YFlushAsync(pMC, pWriteSizer, pContext).ConfigureAwait(false); } }
protected async override Task YWriteLineAsync(cMethodControl pMC, List <byte> pLine, cBatchSizer pWriteSizer, cTrace.cContext pContext) { byte lByte; // special case if (pLine.Count == 0) { return; } // strip trailing space int lEOL = pLine.Count; while (true) { lByte = pLine[lEOL - 1]; if (lByte != cASCII.SPACE && lByte != cASCII.TAB) { break; } if (--lEOL == 0) { return; } } // strip trailing = bool lSoftLineBreak; if (pLine[lEOL - 1] == cASCII.EQUALS) { if (--lEOL == 0) { return; } lSoftLineBreak = true; } else { lSoftLineBreak = false; } // decode mBytes.Clear(); int lInputByte = 0; while (lInputByte < lEOL) { lByte = pLine[lInputByte++]; if (lByte == cASCII.EQUALS) { if (lInputByte + 2 <= lEOL && ZGetHexEncodedNibble(pLine, lInputByte, out int lMSN) && ZGetHexEncodedNibble(pLine, lInputByte + 1, out int lLSN)) { lInputByte = lInputByte + 2; lByte = (byte)(lMSN << 4 | lLSN); } } mBytes.Add(lByte); } if (!lSoftLineBreak) { mBytes.Add(cASCII.CR); mBytes.Add(cASCII.LF); } await YWriteAsync(pMC, mBytes, 0, pWriteSizer, pContext).ConfigureAwait(false); }