public cResponse BuildFromBuffer(byte[] pBuffer, ref int pBufferPosition, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cResponseBuilder), nameof(BuildFromBuffer)); while (pBufferPosition < pBuffer.Length) { byte lByte = pBuffer[pBufferPosition++]; if (mBytesToGo == 0) { if (mBufferedCR) { mBufferedCR = false; if (lByte == cASCII.LF) { if (ZBuildLineFromBytes(lContext)) { cResponse lResponse = new cResponse(mLines); mLines = new List <cResponseLine>(); return(lResponse); } continue; } mBytes.Add(cASCII.CR); } if (lByte == cASCII.CR) { mBufferedCR = true; } else { mBytes.Add(lByte); } } else { mBytes.Add(lByte); if (--mBytesToGo == 0) { ZAddWholeLine(true, lContext); } } } return(null); }
private async Task ZFetchCacheItemsAsync(cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cCacheItemFetchConfiguration pConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZFetchCacheItemsAsync), pMessageHandles, pItems); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || lSession.ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pMessageHandles == null) { throw new ArgumentNullException(nameof(pMessageHandles)); } if (pItems == null) { throw new ArgumentNullException(nameof(pItems)); } if (pMessageHandles.Count == 0) { return; } if (pItems.IsEmpty) { return; } if (pConfiguration == null) { using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); var lProgress = new cProgress(); await lSession.FetchCacheItemsAsync(lMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false); } } else { var lMC = new cMethodControl(pConfiguration.Timeout, pConfiguration.CancellationToken); var lProgress = new cProgress(mSynchroniser, pConfiguration.Increment); await lSession.FetchCacheItemsAsync(lMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false); } }
public void CommandCompletion(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cMailboxCache), nameof(CommandCompletion)); if (mSelectedMailbox == null) { return; } if (mSelectedMailbox.MessageCache.NoModSeq) { return; } mSelectedMailbox.UpdateHighestModSeq(lContext); }
} = null; // note that this body may start before the origin position requested and may be longer or shorter than requested public override eProcessDataResult ProcessData(cResponseData pData, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandHookFetchBody), nameof(ProcessData)); if (!(pData is cResponseDataFetch lFetch)) { return(eProcessDataResult.notprocessed); } if (!IsThisTheMessageThatIAmInterestedIn(lFetch)) { return(eProcessDataResult.notprocessed); } eProcessDataResult lResult = eProcessDataResult.notprocessed; foreach (var lBody in lFetch.Bodies) { uint lOrigin = (lBody.Origin ?? 0); if (lBody.Binary == mBinary && lBody.Section == mSection && lOrigin <= mOrigin) { if (lBody.Bytes == null) { // this is the case where NIL is returned by the server (e.g. * 1 FETCH (BODY[] NIL)) // most likely because the message has been expunged if (lOrigin >= mOrigin) { lResult = eProcessDataResult.observed; } } else { uint lTo = lOrigin + (uint)lBody.Bytes.Count; if (lTo >= mOrigin) { lResult = eProcessDataResult.observed; if (Body == null || lTo > mTo) { Body = lBody; mTo = lTo; } } } } } return(lResult); }
public override void CommandCompleted(cCommandResult pResult, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandHookStore), nameof(CommandCompleted), pResult); if (pResult.ResultType == eCommandResultType.ok && mUIDStoreFeedback != null) { // find the handles for the UIDs, if possible // (this is to enhance the ability to tell if the store was successful or not for a UIDStore) foreach (var lItem in mUIDStoreFeedback) { lItem.MessageHandle = mSelectedMailbox.GetHandle(lItem.UID); } } }
/// <summary> /// Issues a disposable token object containing a <see cref="CancellationToken"/>. /// </summary> /// <param name="pParentContext">Context for trace messages.</param> /// <returns></returns> /// <remarks> /// Issuing the token object increments <see cref="Count"/>. /// Use the <see cref="CancellationToken"/> wrapped by the token object to control <see langword="async"/> operation(s). /// Dispose the token object when the operation(s) complete. /// Disposing the token object 'returns' the token and decrements <see cref="Count"/>. /// </remarks> public cToken GetToken(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCancellationManager), nameof(GetToken)); if (mDisposed) { throw new ObjectDisposedException(nameof(cCancellationManager)); } lock (mCurrentCancellationSetLock) { return(mCurrentCancellationSet.GetToken(lContext)); } }
public async Task ConnectAsync(cMethodControl pMC, cServer pServer, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ConnectAsync), pMC, pServer); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.notconnected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnconnected); } ZSetState(eConnectionState.connecting, lContext); sGreeting lGreeting; try { lGreeting = await mPipeline.ConnectAsync(pMC, pServer, lContext).ConfigureAwait(false); } catch (Exception) { ZSetState(eConnectionState.disconnected, lContext); throw; } if (lGreeting.Type == eGreetingType.bye) { ZSetState(eConnectionState.disconnected, lContext); if (ZSetHomeServerReferral(lGreeting.ResponseText, lContext)) { throw new cHomeServerReferralException(lGreeting.ResponseText, lContext); } throw new cConnectByeException(lGreeting.ResponseText, lContext); } if (mPipeline.Capabilities != null) { ZSetCapabilities(mPipeline.Capabilities, mPipeline.AuthenticationMechanisms, lContext); } if (lGreeting.Type == eGreetingType.ok) { ZSetState(eConnectionState.notauthenticated, lContext); return; } // preauth ZSetHomeServerReferral(lGreeting.ResponseText, lContext); ZSetConnectedAccountId(new cAccountId(pServer.Host, eAccountType.unknown), lContext); }
private async Task ZUIDStoreAsync(iMailboxHandle pMailboxHandle, cUIDStoreFeedback pFeedback, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZUIDStoreAsync), pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || lSession.SelectedMailboxDetails?.SelectedForUpdate != true) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate); } if (pMailboxHandle == null) { throw new ArgumentNullException(nameof(pMailboxHandle)); } if (pFeedback == null) { throw new ArgumentNullException(nameof(pFeedback)); } if (pFlags == null) { throw new ArgumentNullException(nameof(pFlags)); } if (pIfUnchangedSinceModSeq == 0) { throw new ArgumentOutOfRangeException(nameof(pIfUnchangedSinceModSeq)); } if (pIfUnchangedSinceModSeq != null && !lSession.Capabilities.CondStore) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.CondStoreNotInUse); } if (pFeedback.Count == 0) { return; } // it is valid to add or remove zero flags according to the ABNF (!) using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); await lSession.UIDStoreAsync(lMC, pMailboxHandle, pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq, lContext).ConfigureAwait(false); } }
public async Task EnableAsync(cMethodControl pMC, fEnableableExtensions pExtensions, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(EnableAsync), pMC, pExtensions); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.authenticated) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotAuthenticated); } using (var lBuilder = new cCommandDetailsBuilder()) { // note the lack of locking - this can only called during connect lBuilder.BeginList(eListBracketing.none); lBuilder.Add(kEnableCommandPartEnable); if ((pExtensions & fEnableableExtensions.utf8) != 0) { lBuilder.Add(kEnableCommandPartUTF8); } // more here as required lBuilder.EndList(); var lHook = new cEnableCommandHook(); lBuilder.Add(lHook); var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false); if (lResult.ResultType == eCommandResultType.ok) { var lEnabledExtensions = lHook.EnabledExtensions; lContext.TraceInformation("enabled extensions {0}", lEnabledExtensions); EnabledExtensions = EnabledExtensions | lEnabledExtensions; lContext.TraceVerbose("current enabled extensions {0}", EnabledExtensions); mSynchroniser.InvokePropertyChanged(nameof(cIMAPClient.EnabledExtensions), lContext); return; } if (lHook.EnabledExtensions != fEnableableExtensions.none) { lContext.TraceError("received enabled on a failed enable"); } throw new cProtocolErrorException(lResult, fCapabilities.enable, lContext); } }
public void SetInitialised(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(SetInitialised)); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.enabled) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotEnabled); } ZSetState(eConnectionState.notselected, lContext); }
public void SetListFlags(cListFlags pListFlags, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cMailboxCacheItem), nameof(SetListFlags), pListFlags); if (pListFlags == null) { throw new ArgumentNullException(nameof(pListFlags)); } fMailboxProperties lDifferences = ZSetExists((pListFlags.Flags & fListFlags.nonexistent) == 0) | cListFlags.Differences(mListFlags, pListFlags); mListFlags = pListFlags; mSynchroniser.InvokeMailboxPropertiesChanged(this, lDifferences, lContext); }
public void ResetExists(cMailboxPathPattern pPattern, int pSequence, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cMailboxCache), nameof(ResetExists), pPattern, pSequence); foreach (var lItem in mDictionary.Values) { if (lItem.Exists != false && lItem.MailboxName != null && pPattern.Matches(lItem.MailboxName.Path)) { if (lItem.ListFlags == null || lItem.ListFlags.Sequence < pSequence) { lItem.ResetExists(lContext); } } } }
private async Task ZProcessChallengeAsync(cBytesCursor pCursor, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(ZProcessChallengeAsync)); IList <byte> lResponse; if (cBase64.TryDecode(pCursor.GetRestAsBytes(), out var lChallenge, out var lError)) { try { lResponse = mCurrentCommand.GetAuthenticationResponse(lChallenge); } catch (Exception e) { lContext.TraceException("SASL authentication object threw", e); lResponse = null; } }
/// <summary> /// Completes the current coordinating task. /// </summary> /// <param name="pParentContext">Context for trace messages.</param> public void Release(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cReleaser), nameof(Release), mName, mInstance); if (mDisposed) { throw new ObjectDisposedException(nameof(cReleaser)); } if (mSemaphoreSlim.CurrentCount == 0) { lContext.TraceVerbose("releasing semaphore"); mSemaphoreSlim.Release(); } }
public void InvokeNetworkSend(int?pBytes, IEnumerable <cBytes> pBuffers, cTrace.cContext pParentContext) { if (NetworkSend == null) { return; // pre-check for efficiency only } var lContext = pParentContext.NewMethod(nameof(cCallbackSynchroniser), nameof(InvokeNetworkSend)); if (mDisposed) { throw new ObjectDisposedException(nameof(cCallbackSynchroniser)); } ZInvokeAndForget(new cNetworkSendEventArgs(pBytes, pBuffers), lContext); // NOTE the event is fired by parallel code in the ZInvokeEvents routine: when adding an event you must put code there also }
/// <summary> /// Disposes the current coordinating task if it is complete, allowing a new coordinating task to be started. /// </summary> /// <param name="pParentContext">Context for trace messages.</param> public void Reset(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cReleaser), nameof(Reset), mName, mInstance); if (mDisposed) { throw new ObjectDisposedException(nameof(cReleaser)); } if (!ZTask(lContext).IsCompleted) { return; } mTask.Dispose(); mTask = null; }
public void InvokeActionInt(Action <int> pAction, int pInt, cTrace.cContext pParentContext) { if (pAction == null) { return; } var lContext = pParentContext.NewMethod(nameof(cCallbackSynchroniser), nameof(InvokeActionInt), pInt); if (mDisposed) { throw new ObjectDisposedException(nameof(cCallbackSynchroniser)); } ZInvokeAndForget(new cActionIntEventArgs(pAction, pInt), lContext); // NOTE the event is fired by parallel code in the ZInvokeEvents routine: when adding an event you must put code there also }
public void InstallTLS(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(InstallTLS)); if (mDisposed) { throw new ObjectDisposedException(nameof(cCommandPipeline)); } if (mState != eState.connected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected); } mConnection.InstallTLS(lContext); }
public override void CommandCompleted(cCommandResult pResult, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandHookAuthenticate), nameof(CommandCompleted), pResult); if (pResult.ResultType != eCommandResultType.ok) { return; } var lSecurity = mAuthentication.GetSecurity(); if (lSecurity != null) { mPipeline.InstallSASLSecurity(lSecurity, lContext); } }
public void InvokeNetworkReceive(cResponse pResponse, cTrace.cContext pParentContext) { if (NetworkReceive == null) { return; // pre-check for efficiency only } var lContext = pParentContext.NewMethod(nameof(cCallbackSynchroniser), nameof(NetworkReceive)); if (mDisposed) { throw new ObjectDisposedException(nameof(cCallbackSynchroniser)); } ZInvokeAndForget(new cNetworkReceiveEventArgs(pResponse), lContext); // NOTE the event is fired by parallel code in the ZInvokeEvents routine: when adding an event you must put code there also }
public void InvokeMailboxMessageDelivery(iMailboxHandle pMailboxHandle, cMessageHandleList pMessageHandles, cTrace.cContext pParentContext) { if (MailboxMessageDelivery == null) { return; // pre-check for efficiency only } var lContext = pParentContext.NewMethod(nameof(cCallbackSynchroniser), nameof(InvokeMailboxMessageDelivery), pMailboxHandle, pMessageHandles); if (mDisposed) { throw new ObjectDisposedException(nameof(cCallbackSynchroniser)); } ZInvokeAndForget(new cMailboxMessageDeliveryEventArgs(pMailboxHandle, pMessageHandles), lContext); // NOTE the event is fired by parallel code in the ZInvokeEvents routine: when adding an event you must put code there also }
public void InvokeCancellableCountChanged(cTrace.cContext pParentContext) { if (PropertyChanged == null) { return; // pre-check for efficiency only } var lContext = pParentContext.NewMethod(nameof(cCallbackSynchroniser), nameof(InvokeCancellableCountChanged)); if (mDisposed) { throw new ObjectDisposedException(nameof(cCallbackSynchroniser)); } ZInvokeAndForget(new PropertyChangedEventArgs(nameof(cIMAPClient.CancellableCount)), lContext); // NOTE the event is fired by parallel code in the ZInvokeEvents routine: when adding an event you must put code there also }
/// <summary> /// Starts a new countdown. /// </summary> /// <param name="pParentContext">Context for trace messages.</param> /// <remarks> /// If the current countdown is still running, this method will throw. /// </remarks> public void Restart(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCountdownTimer), nameof(Restart)); if (mDisposed) { throw new ObjectDisposedException(nameof(cCountdownTimer)); } if (mTask == null || !mTask.IsCompleted) { throw new InvalidOperationException("current countdown not complete"); } mTask.Dispose(); mTask = Task.Delay(mTimeout, mCancellationTokenSource.Token); }
public void Select(iMailboxHandle pMailboxHandle, bool pForUpdate, bool pAccessReadOnly, bool pUIDNotSticky, cFetchableFlags pFlags, cPermanentFlags pPermanentFlags, int pExists, int pRecent, uint pUIDNext, uint pUIDValidity, uint pHighestModSeq, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cMailboxCache), nameof(Select), pMailboxHandle, pForUpdate, pAccessReadOnly, pUIDNotSticky, pFlags, pPermanentFlags, pExists, pRecent, pUIDNext, pUIDValidity, pHighestModSeq); if (mSelectedMailbox != null) { throw new InvalidOperationException(); } if (pMailboxHandle == null) { throw new ArgumentNullException(nameof(pMailboxHandle)); } if (pFlags == null) { throw new ArgumentNullException(nameof(pFlags)); } var lItem = CheckHandle(pMailboxHandle); if (pExists < 0) { throw new ArgumentOutOfRangeException(nameof(pExists)); } if (pRecent < 0) { throw new ArgumentOutOfRangeException(nameof(pRecent)); } mSelectedMailbox = new cSelectedMailbox(mSynchroniser, lItem, pForUpdate, pAccessReadOnly, pExists, pRecent, pUIDNext, pUIDValidity, pHighestModSeq, lContext); lItem.SetSelectedProperties(pUIDNotSticky, pFlags, pForUpdate, pPermanentFlags, lContext); fMailboxProperties lProperties = fMailboxProperties.isselected; if (pForUpdate) { lProperties |= fMailboxProperties.isselectedforupdate; } if (pAccessReadOnly) { lProperties |= fMailboxProperties.isaccessreadonly; } mSetState(eConnectionState.selected, lContext); mSynchroniser.InvokeMailboxPropertiesChanged(pMailboxHandle, lProperties, lContext); mSynchroniser.InvokePropertyChanged(nameof(cIMAPClient.SelectedMailbox), lContext); }
internal static void _Tests(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cMailboxName), nameof(_Tests)); _Tests_MailboxName("", true, lContext); _Tests_MailboxName("/", true, lContext); _Tests_MailboxName("fred", false, lContext); _Tests_MailboxName("fred/", true, lContext); _Tests_MailboxName("/fred", false, lContext); _Tests_MailboxName("/fred/", true, lContext); _Tests_MailboxName("fred/fr€d", false, lContext); _Tests_MailboxName("fred/fr€d/", true, lContext); _Tests_MailboxName("/fred/fr€d", false, lContext); _Tests_MailboxName("/fred/fr€d/", true, lContext); }
/// <summary> /// May return a disposable object that represents a block on the issue of exclusive access. /// This method will return a block if the exclusive access is not currently granted, otherwise it will return <see langword="null"/>. /// Dispose the returned object (if any) to release the block. /// </summary> /// <param name="pParentContext">Context for trace messages.</param> /// <returns></returns> public cBlock TryGetBlock(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cExclusiveAccess), nameof(TryGetBlock), mName, mInstance); if (mDisposed) { throw new ObjectDisposedException(nameof(cExclusiveAccess)); } if (!mExclusiveSemaphoreSlim.Wait(0)) { return(null); } Interlocked.Increment(ref mBlocks); mExclusiveSemaphoreSlim.Release(); return(new cBlock(mName, mSequence, mInstance, ZReleaseBlock, pParentContext)); }
public override eProcessDataResult ProcessData(cResponseData pData, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandHookListMailboxes), nameof(ProcessData)); if (!(pData is cResponseDataListMailbox lListMailbox)) { return(eProcessDataResult.notprocessed); } if (!mPattern.Matches(lListMailbox.MailboxName.Path)) { return(eProcessDataResult.notprocessed); } mMailboxes.Add(lListMailbox.MailboxName); return(eProcessDataResult.observed); }
public static void _Tests(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(_Tests)); cCommandPipeline._Tests(lContext); cIdDataProcessor._Tests(lContext); cNamespaceDataProcessor._Tests(lContext); //cCommandHookList._Tests(lContext); //cCommandHookLSub._Tests(lContext); //cListExtendedCommandHook._Tests(lContext); cResponseDataParserFetch._Tests(lContext); cResponseDataParserESearch._Tests(lContext); //_Tests_ListExtendedCommandParts(lContext); cCommandDetailsBuilder._Tests(lContext); cQuotedPrintableDecoder._Tests(lContext); }
private void ZAuthenticated(cStrings pOldPipelineCapabilities, cCommandHookInitial pHook, cResponseText pResponseText, cAccountId pAccountId, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZAuthenticated)); if (pHook.Capabilities != null) { ZSetCapabilities(pHook.Capabilities, pHook.AuthenticationMechanisms, lContext); } else if (!ReferenceEquals(pOldPipelineCapabilities, mPipeline.Capabilities)) { ZSetCapabilities(mPipeline.Capabilities, mPipeline.AuthenticationMechanisms, lContext); } ZSetHomeServerReferral(pResponseText, lContext); ZSetConnectedAccountId(pAccountId, lContext); }
public bool GetURL(out cURLParts rParts, out string rString, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cBytesCursor), nameof(GetURL)); var lBookmark = Position; if (!cURLParts.Process(this, out rParts, lContext)) { Position = lBookmark; rString = null; return(false); } rString = GetFromAsString(lBookmark); return(true); }