I am developing a UWP VPN application and I recently noticed that after a successful connection, no data was sent through the tunnel. While debugging, I noticed that the call to StartExistingTransports() never returned.
This started after I upgraded my development machine to Windows 10 2004 (it was working fine in the previous version: 1903) and it happens every time.
I do not see any errors but the thread is stuck.
I have created a new solution with only the bare minimum in order to test and the same happens. I can not attach the whole solution but here are the main classes.
MainPage.xaml.cs:
public sealed partial class MainPage : Page
{
private readonly VpnManagementAgent vpnManagementAgent = new VpnManagementAgent();
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
const string profileName = "profileName";
var profile = await this.GetProfileByNameAsync(profileName);
if (profile != null)
{
// We can't update the IP/URI in the profile so deletes it instead
var deleteProfileStatus = await this.vpnManagementAgent.DeleteProfileAsync(profile);
if (deleteProfileStatus != 0)
{
throw new InvalidOperationException($"Could not delete VPN profile. Error code: {deleteProfileStatus}.");
}
}
profile = new VpnPlugInProfile
{
ServerUris = { new Uri("https://10.1.2.3") },
ProfileName = profileName,
AlwaysOn = false,
VpnPluginPackageFamilyName = Package.Current.Id.FamilyName
};
var addProfileStatus = await this.vpnManagementAgent.AddProfileFromObjectAsync(profile);
if (addProfileStatus != 0)
{
throw new InvalidOperationException($"Could not create VPN profile. Error code: {addProfileStatus}.");
}
Debug.WriteLine($"Connecting profile name: {profile.ProfileName}");
var errorCode = await this.vpnManagementAgent.ConnectProfileAsync(profile);
Debug.WriteLine($"Connecting attempt resulted in error code: {errorCode}");
}
private async Task<VpnPlugInProfile> GetProfileByNameAsync(string profileName)
{
var profiles = await this.vpnManagementAgent.GetProfilesAsync();
foreach (var p in profiles)
{
if (p is VpnPlugInProfile profile &&
profile.VpnPluginPackageFamilyName.Equals(Package.Current.Id.FamilyName) &&
profile.ProfileName.Equals(profileName))
{
return profile;
}
}
return null;
}
}
VpnBackgroundTask.cs:
public sealed class VpnBackgroundTask : IBackgroundTask
{
private static SslVpnPlugin vpnPlugin;
private BackgroundTaskDeferral serviceDeferral;
/// <inheritdoc />
public void Run(IBackgroundTaskInstance taskInstance)
{
//Take a service deferral so the service isn't terminated
this.serviceDeferral = taskInstance.GetDeferral();
if (VpnBackgroundTask.vpnPlugin == null)
{
VpnBackgroundTask.vpnPlugin = new SslVpnPlugin();
taskInstance.Canceled += this.OnTaskCanceled;
}
VpnChannel.ProcessEventAsync(VpnBackgroundTask.vpnPlugin, taskInstance.TriggerDetails);
}
private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
if (this.serviceDeferral != null)
{
//Complete the service deferral
this.serviceDeferral.Complete();
this.serviceDeferral = null;
}
}
}
SslVpnPlugin.cs
public sealed class SslVpnPlugin : IVpnPlugIn
{
StreamSocket Socket = new StreamSocket();
public void Connect(VpnChannel channel)
{
try
{
channel.AssociateTransport(this.Socket, null);
var myAddress = new List<HostName>
{
new HostName("192.168.80.100")
};
var myRoute = new VpnRouteAssignment();
myRoute.Ipv4InclusionRoutes.Add(new VpnRoute(new HostName("192.168.80.0"), 24));
Debug.WriteLine("Calling channel.StartExistingTransports()");
// This call will block
channel.StartExistingTransports(myAddress,
null,
null,
myRoute,
null,
1472,
1500,
false);
Debug.WriteLine("channel.StartExistingTransports() returned");
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
Debug.WriteLine("Connected");
}
public void Disconnect(VpnChannel channel)
{
throw new System.NotImplementedException();
}
public void GetKeepAlivePayload(VpnChannel channel, out VpnPacketBuffer keepAlivePacket)
{
throw new System.NotImplementedException();
}
public void Encapsulate(VpnChannel channel, VpnPacketBufferList packets, VpnPacketBufferList encapulatedPackets)
{
throw new System.NotImplementedException();
}
public void Decapsulate(VpnChannel channel, VpnPacketBuffer encapBuffer, VpnPacketBufferList decapsulatedPackets,
VpnPacketBufferList controlPacketsToSend)
{
throw new System.NotImplementedException();
}
}