The stream upgrade provider needs to do three things:
using System;using System.ServiceModel;using System.ServiceModel.Channels;namespace Microsoft.ServiceModel.Samples{ class OpenAsyncResult : CompletedAsyncResult { internal OpenAsyncResult(AsyncCallback callback, object state) : base(callback, state) { } } class CloseAsyncResult : CompletedAsyncResult { internal CloseAsyncResult(AsyncCallback callback, object state) : base(callback, state) { } } class ROT128StreamUpgradeProvider : StreamUpgradeProvider { public ROT128StreamUpgradeProvider(ROT128StreamUpgradeBindingElement element, BindingContext context) : base(context.Binding) { } public override StreamUpgradeAcceptor CreateUpgradeAcceptor() { return new ROT128StreamUpgradeAcceptor(this); } public override StreamUpgradeInitiator CreateUpgradeInitiator(EndpointAddress remoteAddress, Uri via) { return new ROT128StreamUpgradeInitiator(this, remoteAddress, via); } protected override void OnAbort() { } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { return new CloseAsyncResult(callback, state); } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { return new OpenAsyncResult(callback, state); } protected override void OnClose(TimeSpan timeout) { } protected override void OnEndClose(IAsyncResult result) { } protected override void OnEndOpen(IAsyncResult result) { } protected override void OnOpen(TimeSpan timeout) { } }}
I've used the AsyncResult class from our SDK samples so that I don't have to keep implementing these myself. I'm going to be using a contract-based client and server in this example, which calls the asynchronous code paths by default. I've also added the helper class as an attachment to this post.
Next time: ROT 128 Stream Upgrade Sample, Part 4