public cCommandPipeline(cCallbackSynchroniser pSynchroniser, Action <cTrace.cContext> pDisconnected, cBatchSizerConfiguration pNetworkWriteConfiguration, cIdleConfiguration pIdleConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewObject(nameof(cCommandPipeline), pIdleConfiguration); mSynchroniser = pSynchroniser ?? throw new ArgumentNullException(nameof(pSynchroniser)); mDisconnected = pDisconnected ?? throw new ArgumentNullException(nameof(pDisconnected)); if (pNetworkWriteConfiguration == null) { throw new ArgumentNullException(nameof(pNetworkWriteConfiguration)); } mConnection = new cConnection(pNetworkWriteConfiguration); mIdleConfiguration = pIdleConfiguration; mResponseTextProcessor = new cResponseTextProcessor(pSynchroniser); // these depend on the cancellationtokensource being constructed mBackgroundReleaser = new cReleaser("commandpipeline_background", mBackgroundCancellationTokenSource.Token); mBackgroundAwaiter = new cAwaiter(mBackgroundCancellationTokenSource.Token); mBackgroundSendBuffer = new cSendBuffer(pSynchroniser, mConnection, mBackgroundCancellationTokenSource.Token); // plumbing mIdleBlock.Released += mBackgroundReleaser.Release; // when the idle block is removed, kick the background process }
public async Task <sGreeting> ConnectAsync(cMethodControl pMC, cServer pServer, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(ConnectAsync), pMC, pServer); if (mDisposed) { throw new ObjectDisposedException(nameof(cCommandPipeline)); } if (mState != eState.notconnected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnconnected); } mState = eState.connecting; try { await mConnection.ConnectAsync(pMC, pServer, lContext).ConfigureAwait(false); using (var lAwaiter = new cAwaiter(pMC)) { while (true) { lContext.TraceVerbose("waiting"); await lAwaiter.AwaitAny(mConnection.GetBuildResponseTask(lContext)).ConfigureAwait(false); var lResponse = mConnection.GetResponse(lContext); mSynchroniser.InvokeNetworkReceive(lResponse, lContext); var lCursor = new cBytesCursor(lResponse); if (lCursor.SkipBytes(kGreetingAsteriskSpaceOKSpace)) { var lHook = new cCommandHookInitial(); cResponseText lResponseText = mResponseTextProcessor.Process(eResponseTextContext.greetingok, lCursor, lHook, lContext); lContext.TraceVerbose("got ok: {0}", lResponseText); mState = eState.connected; mBackgroundTask = ZBackgroundTaskAsync(lContext); mCapabilities = lHook.Capabilities; mAuthenticationMechanisms = lHook.AuthenticationMechanisms; return(new sGreeting(eGreetingType.ok, null)); } if (lCursor.SkipBytes(kGreetingAsteriskSpacePreAuthSpace)) { var lHook = new cCommandHookInitial(); cResponseText lResponseText = mResponseTextProcessor.Process(eResponseTextContext.greetingpreauth, lCursor, lHook, lContext); lContext.TraceVerbose("got preauth: {0}", lResponseText); mState = eState.connected; mBackgroundTask = ZBackgroundTaskAsync(lContext); mCapabilities = lHook.Capabilities; mAuthenticationMechanisms = lHook.AuthenticationMechanisms; return(new sGreeting(eGreetingType.preauth, lResponseText)); } if (lCursor.SkipBytes(kGreetingAsteriskSpaceBYESpace)) { cResponseText lResponseText = mResponseTextProcessor.Process(eResponseTextContext.greetingbye, lCursor, null, lContext); lContext.TraceError("got bye: {0}", lResponseText); mConnection.Disconnect(lContext); mState = eState.stopped; return(new sGreeting(eGreetingType.bye, lResponseText)); } lContext.TraceError("unrecognised response: {0}", lResponse); } } } catch (Exception) { mConnection.Disconnect(lContext); mState = eState.stopped; throw; } }