What exception is thrown by ReadBufferAsync when there is no internet connectivity - c#

When getting data from the net, how can I tell if I failed to connect?
I am using GetBufferAsync, which throws an error when I pull the ethernet cable out of the computer.
I can find no documentation about this error, and I don't know if this is the best method to use.
I am loading a text file that is up to 60Kb. Not very much data.
I am developing in Visual Studio 2019.
The code below loads some data from www.google.com, mostly 0's.
When I disconnect the ethernet cable, I get exception thrown at the ReadBufferAsync line.
I tried catching specific exceptions: InvalidOperationException, HttpRequestException
Error: 0x8002ee7 (decimal 12007).
Text: The text associated with this error code could not be found. The server name or address could not be resolved.
InnerException: null
The MS documentation https://learn.microsoft.com/en-us/windows/desktop/WinInet/wininet-errors does not include the error I'm getting, though my exception is in the correct range (see https://learn.microsoft.com/en-us/windows/desktop/Debug/system-error-codes--12000-15999-)
using System;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web.Http;
namespace ReadBufferAsyncTest
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.Loaded += MyProgram_Loaded;
}
private async void MyProgram_Loaded(object sender, RoutedEventArgs e)
{
try
{
// Connecting to internet
var uriBing = new Uri("http://www.google.com");
var client = new HttpClient();
IBuffer morseBuffer = await client.GetBufferAsync(uriBing);
DataReader dataReader = DataReader.FromBuffer(morseBuffer);
byte[] morseBytes = new byte[morseBuffer.Length];
dataReader.ReadBytes(morseBytes);
}
catch(Exception ex)
{
return; // breakpoint goes here
}
}
}
}
Is the error I am getting (0x80072ee7) the expected error?
Are there other errors to look for?
What is the best way to handle the errors when there is limited documentation?
(other note: is this the best way to download a small text file?)

how can I tell if I failed to connect?
For your requirement, you could check if the internet is available before getting buffer via NetworkHelper.
// Detect if Internet can be reached
if (NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable)
{
}

Related

C# / UWP / MVVM - How to handle HttpClient exceptions when the server is unrechable

I am currently working on an UWP app, that will run on a Raspberry PI. Most of my application can be used without an internet connection, but parts of it rely on fetching data from a server ran locally.
My issue is that whenever the server is offline, I can not handle the exceptions raised by the HttpClient.
To avoid using async tasks in the constructor of the ViewModel, I've moved it to the OnLoaded method of the View.
These are the methods that I use:
HomeAssistantView
private async void OnLoaded(object sender, RoutedEventArgs e)
{
await ViewModel.LoadEntities();
}
HomeAssistantViewModel
public async Task LoadEntities()
{
var entityList = await _homeAssistantService.LoadEntities();
Switches = new ObservableCollection<HomeAssistantSwitchEntity>(entityList.OfType<HomeAssistantSwitchEntity>());
Entities = new ObservableCollection<HomeAssistantEntity>(entityList.Where(entity =>!(entity is HomeAssistantSwitchEntity)));
}
HomeAssistantService
public async Task<List<HomeAssistantEntity>> LoadEntities()
{
_client.BaseAddress = new Uri(_homeAssistantURL);
_client.DefaultRequestHeaders.Add("Authorization", $"Bearer {_homeAssistantToken}");
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
HttpResponseMessage response = await _client.GetAsync("api/states");
if (response.IsSuccessStatusCode)
{
return DeserializeConfigFile(await response.Content.ReadAsStringAsync());
}
}
catch (HttpRequestException e)
{
Debug.WriteLine(e.Message);
}
return new List<HomeAssistantEntity>();
}
Even though I've added a try block, the application raises a System.Exception, with the message "The server name or address could not be resolved". After disabling the generic Exception type in the settings, Visual Studio told me it was a type of HttpRequestException with the message An error occurred while sending the request.
In a different part of my application, where I use a weather API, I got away with using the NetworkInformation.GetInternetConnectionProfile() to check whether there is an internet connection available prior to sending a request, but it's not a viable option here. Also, I've thought of sending a ping to the server prior to trying to fetch the data, but as far as I'm concerned, pinging is not available on the Windows 10 IoT Core.
I understood, that, you don't want the exception to be thrown, is this correct?
If yes just replace
catch (HttpRequestException e)
{
Debug.WriteLine(e.Message);
}
with
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
this will catch all occuring exceptions

How to programmatically pair a bluetooth device

I recently bought a Lilypad Simblee BLE Board and I'd like to pair it programmatically to my computer (using the 32feet.NET library in C#).
I'm aware the "How to programmatically pair a bluetooth device" has already been asked on StackOverflow (here for example), however for some reason, all my attempts to pair the device programmatically have failed. Indeed, I successfully paired the device with the "Manage Bluetooth devices" window in Windows 10 Settings panel (Settings > Devices > Bluetooth).
Firstly, I don't know the pairing method (either legacy or SSP) to use with my device. Windows never asked me for a PIN or something, so I guess it's SSP, but I'm unsure.
I searched on Google how to do a SSP pairing request with 32feet.NET: I found this.
However, once it discovered my device (the device discovery works properly), the pairing request instantly fails.
My code:
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Sockets;
using System;
using System.Collections.Generic;
namespace HLK_Client
{
class HLKBoard
{
public event HLKBoardEventHandler HLKBoardConnectionComplete;
public delegate void HLKBoardEventHandler(object sender, HLKBoardEventArgs e);
private BluetoothClient _bluetoothClient;
private BluetoothComponent _bluetoothComponent;
private List<BluetoothDeviceInfo> _inRangeBluetoothDevices;
private BluetoothDeviceInfo _hlkBoardDevice;
private EventHandler<BluetoothWin32AuthenticationEventArgs> _bluetoothAuthenticatorHandler;
private BluetoothWin32Authentication _bluetoothAuthenticator;
public HLKBoard()
{
_bluetoothClient = new BluetoothClient();
_bluetoothComponent = new BluetoothComponent(_bluetoothClient);
_inRangeBluetoothDevices = new List<BluetoothDeviceInfo>();
_bluetoothAuthenticatorHandler = new EventHandler<BluetoothWin32AuthenticationEventArgs>(_bluetoothAutenticator_handlePairingRequest);
_bluetoothAuthenticator = new BluetoothWin32Authentication(_bluetoothAuthenticatorHandler);
_bluetoothComponent.DiscoverDevicesProgress += _bluetoothComponent_DiscoverDevicesProgress;
_bluetoothComponent.DiscoverDevicesComplete += _bluetoothComponent_DiscoverDevicesComplete;
}
public void ConnectAsync()
{
_inRangeBluetoothDevices.Clear();
_hlkBoardDevice = null;
_bluetoothComponent.DiscoverDevicesAsync(255, true, true, true, false, null);
}
private void PairWithBoard()
{
Console.WriteLine("Pairing...");
bool pairResult = BluetoothSecurity.PairRequest(_hlkBoardDevice.DeviceAddress, null);
if (pairResult)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Fail"); // Instantly fails
}
}
private void _bluetoothComponent_DiscoverDevicesProgress(object sender, DiscoverDevicesEventArgs e)
{
_inRangeBluetoothDevices.AddRange(e.Devices);
}
private void _bluetoothComponent_DiscoverDevicesComplete(object sender, DiscoverDevicesEventArgs e)
{
for (int i = 0; i < _inRangeBluetoothDevices.Count; ++i)
{
if (_inRangeBluetoothDevices[i].DeviceName == "HLK")
{
_hlkBoardDevice = _inRangeBluetoothDevices[i];
PairWithBoard();
return;
}
}
HLKBoardConnectionComplete(this, new HLKBoardEventArgs(false, "Didn't found any \"HLK\" discoverable device"));
}
private void _bluetoothAutenticator_handlePairingRequest(object sender, BluetoothWin32AuthenticationEventArgs e)
{
e.Confirm = true; // Never reach this line
}
}
}
Why does the pairing request fail?
The answer to the question you linked has a plausible suggestion... did you read it?
Also you should look at this question as well.
32feet library is built around legacy pairing, so that you either need to know the pin of the device you are connecting to, or you supply it with a null to get a popup window to enter a pin.
It also says that the windows function used by 32feet is deprecated in newer versions of windows. If that's true, the reason it's failing instantly is because you've passed a null pin in your pairing request and for it to proceed windows needs to show a dialog which no longer exists.
What happens if you try to connect with the pin "0000" or "1234" ?
I'm looking at the source code of WindowsBluetoothSecurity.cs in 32feet.net and I see if a pairing request fails, it logs the error code to Debug.WriteLine, any chance you could post that error code here?
One good work around to this problem might be to import BluetoothAuthenticateDeviceEx and use that manually to complete the pairing request. If you don't want to do this manually, it looks like in the latest version of the 32feet source, there is actually a SSP pairing method that utilises this method but it's not public and it's not used anywhere so you'll need to access it via reflection:
typeof(BluetoothSecurity)
.GetMethod("PairRequest", BindingFlags.Static | BindingFlags.NonPublic)
.Invoke(null, new object[] { _hlkBoardDevice.DeviceAddress, BluetoothAuthenticationRequirements.MITMProtectionNotRequired });

TLSharp Data center (dc) Exception

I am using TLSharp library for implementing a custom Telegram client. when I run the code below:
public async Task<string> SendCodeRequest(string phoneNumber)
{
var completed = false;
TL.AuthSendCodeRequest request = null;
while (!completed)
{
request = new TL.AuthSendCodeRequest(phoneNumber, 5, _apiId, _apiHash, "en");
await _sender.Send(request);
await _sender.Receive(request);
completed = true;
}
// TODO handle other types (such as SMS)
if (request.Result is TL.AuthSentCodeType)
{
var result = (TL.AuthSentCodeType)request.Result;
return result.PhoneCodeHash;
}
else
{
var result = (TL.AuthSentAppCodeType)request.Result;
return result.PhoneCodeHash;
}
}
I gives me the following exception :
Your phone number registered to {dcIdx} dc. Please update settings.
See https://github.com/sochix/TLSharp#i-get-an-error-migrate_x for
details.
The mentioned github page says that TLSharp Handles these exceptions by itself. So I guess something is wrong with the library core because the code should resolve data center IPs by itself not generating an exception.
Any help would be appreciated.
TlSharp Currently doesn't handle this exception you have to catch the exception and get the data center number then Try to reconnect to the Data Center using the ReconnectToDc() Function.
In the MtProtoSender.cs file you can find the following line of code that generates the exception:
throw new InvalidOperationException($"Your phone number registered to {dcIdx} dc. Please update settings. See https://github.com/sochix/TLSharp#i-get-an-error-migrate_x for details.");
Replace it with the following code so that the Exception that is generated has the required Data Center number for connecting to it.
InvalidOperationException exception = new InvalidOperationException($"Your phone number registered to {dcIdx} dc. Please update settings. See https://github.com/sochix/TLSharp#i-get-an-error-migrate_x for details.");
exception.Data.Add("dcId", dcIdx);
throw exception;
Change your code like this:
while (!completed)
{
request = new TL.AuthSendCodeRequest(phoneNumber, 5, _apiId, _apiHash, "en");
try
{
await _sender.Send(request);
await _sender.Receive(request);
completed = true;
}
catch (InvalidOperationException ex)
{
if (ex.Message.StartsWith("Your phone number registered to") && ex.Data["dcId"] != null)
{
await ReconnectToDc((int)ex.Data["dcId"]);
}
else
{
throw;
}
}
}
In the Code above the Data Center number that was attached to the Exception is used for reconnecting to the Data center.
Probably your phone number is not in the format accepted by Telegram.
Phone number must start with plus sign, use country code and phone number without gap, for example: +989333333333

Sending an LLDP packet using SharpPcap and Packet.Net

So, I spent the afternoon trying to send an LLDP packet in c# using SharpPcap and Packet.Net.
What I came up with bombs with an NullReferenceException. I know why, but I don't know what to do about it.
This is my code:
namespace LLDPTest {
using System;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;
using PacketDotNet;
using SharpPcap.WinPcap;
class Program {
static void Main(string[] args) {
//var timer = new Timer(state => SendLLDPPacketOnAllInterfaces(), null, 0, 1000);
SendLLDPPacketOnAllInterfaces();
Console.ReadLine();
}
private static void SendLLDPPacketOnAllInterfaces() {
var winPcapDeviceList = WinPcapDeviceList.Instance;
foreach (var device in winPcapDeviceList.Where(device => device.Interface.GatewayAddress != null)) {
SendLLDPPacket(device);
}
}
private static void SendLLDPPacket(WinPcapDevice device) {
var packet = LLDPPacket.RandomPacket();
//packet.Header = ???
var ethernetPacket = new EthernetPacket(device.Addresses[1].Addr.hardwareAddress, PhysicalAddress.Parse("01-80-C2-00-00-0E"), EthernetPacketType.LLDP);
ethernetPacket.PayloadPacket = packet;
device.Open();
device.SendPacket(ethernetPacket);
device.Close();
Console.WriteLine("LLDP packet sent!");
}
}
}
The exception is thrown in in line 36 (device.SendPacket(ethernetPacket);)
The reason for this is that the packet's header property must not be null. The exception is thrown in line 229 of Packet.cs where the following check is performed:
if ((this.header.Bytes != this.payloadPacketOrData.ThePacket.header.Bytes) || ((this.header.Offset + this.header.Length) != this.payloadPacketOrData.ThePacket.header.Offset))
{
return false;
}
Long story short, I simply don't know what I should set the header property to, there are no examples on Google or anywhere else.
EDIT: this.payloadPacketOrData.ThePacket.header is null. This is the packet that results from the call to LLDPPacket.RandomPacket();. Unfortunately the header property has no setter.
EDIT2: I'm using the latest versions of both packets from NuGet.
EDIT3: http://wiki.wireshark.org/LinkLayerDiscoveryProtocol says that
It's interesting to note that unlike the LLDP drafts referenced above,
the final LLDP standard abandoned the notion of an LLDP Header and
instead simply mandated the presence of certain TLVs. In the various
draft documents the LLDP Header was supposed to include a Version
field. The current LLDP standard does not include any notion of a
Version.
Sigh. I have no idea why, but after checking the unit tests (https://github.com/antmicro/Packet.Net/blob/master/Test/PacketType/LldpTest.cs) I stumbled upon the solution (lines 78-79):
var packet = LLDPPacket.RandomPacket();
var lldpBytes = packet.Bytes;
var lldpPacket = new LLDPPacket(new ByteArraySegment(lldpBytes));
I don't know why what the authors call "reparsing" is necessary, but now it works.

32feet.NET: Problem with Bluetooth Listener and GUID value

I am using 32feet.NET library to create a Bluetooth service. But the listener fails to start with an invalid argument was supplied message. This is possibly related to the GUID value supplied. I generated the GUID at design time by using the Tools--->Create Guid menu option in Visual Studio.
Below I am posting the code snippet.
public static void Main()
{
BluetoothListener lsnr = new BluetoothListener(MyConsts.MyServiceUuid);
lsnr.Start();//It throws an Invalid arguement supplied exception
BluetoothClient conn = new BluetoothClient();
conn = lsnr.AcceptBluetoothClient();
Stream peerStream = conn.GetStream();
}
class MyConsts
{
public static Guid MyServiceUuid = new Guid("{1D69EDBD-9862-43fe-A242-98322AE764A4}");
}
Any Ideas??
I think something is wrong with the system. Unplug your dongle and try again, or reboot and see if its fixed.
If that doesn't help let me see the full stack-trace of the exception.
(BTW there's no need to initialise conn).
Alan (32feet.NET maintainer)

Categories