I’ve created a simple program to demonstrate the problem.
using Gadgeteer.Networking;
using GHI.Networking;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Net.NetworkInformation;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;
using System;
using System.Collections;
using System.IO;
using System.IO.Ports;
using System.Net;
using System.Text;
using System.Threading;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
namespace ModemTest
{
public partial class Program
{
private SerialPort port;
private PPPSerialModem modem;
private void ProgramStarted()
{
Debug.Print("Program Started");
NetworkChange.NetworkAvailabilityChanged += (x, y) => { Debug.Print("Network Available: " + y.IsAvailable); };
NetworkChange.NetworkAddressChanged += (x, y) => { Debug.Print("Network Address Changed: " + Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[3].IPAddress); };
//Port is a K socket UART with handshake.
string serialPortName = GT.Socket.GetSocket(4, false, null, "").SerialPortName;
port = new SerialPort(serialPortName, 115200, Parity.None, 8, StopBits.One);
port.Handshake = Handshake.RequestToSend;
port.ReadTimeout = 100;
port.Open();
port.DiscardInBuffer();
port.DiscardOutBuffer();
modem = new PPPSerialModem(port);
new Thread(Work).Start();
}
private void Work()
{
Thread.Sleep(10000);
Debug.Print("Thread Start");
var netIf = NetworkInterface.GetAllNetworkInterfaces()[3];
if (netIf.IsDynamicDnsEnabled)
netIf.EnableStaticDns(new string[] { "198.224.152.119", "198.224.154.135" });
try
{
SendATCommand("ATE0", 1000);
SendATCommand("AT+CSQ", 1000);
SendATCommand("AT+CREG?", 2000);
SendATCommand("ATD#777", 40000);
try
{
modem.Open();
modem.Connect(PPPSerialModem.AuthenticationType.Pap, "", "");
Thread.Sleep(5000);
if (modem.LinkConnected)
{
var activeInterface = BaseInterface.ActiveInterface;
Debug.Print("Active Interface");
Debug.Print(string.Concat("Modem IP: ", activeInterface.IPAddress));
Debug.Print(string.Concat("Modem Gateway: ", activeInterface.GatewayAddress));
Debug.Print(string.Concat("Modem Mask: ", activeInterface.SubnetMask));
Debug.Print(string.Concat("Modem DHCP Enabled: ", activeInterface.IsDhcpEnabled));
Debug.Print(string.Concat("Modem Dynamic DNS Enabled: ", activeInterface.IsDynamicDnsEnabled));
var dnsAddrs = activeInterface.DnsAddresses;
for (int j = 0; j < dnsAddrs.Length; j++)
{
var dns = dnsAddrs[j];
Debug.Print(string.Concat("Modem DNS ", j, ": ", dns));
}
HTTPRequest();
modem.Disconnect();
modem.Close();
}
}
catch (Exception ex)
{
Debug.Print(ex.ToString());
}
SendATCommand("+++", 5000);
SendATCommand("ATH", 3000);
SendATCommand("+++", 5000);
}
catch (Exception ex)
{
Debug.Print(ex.ToString());
}
finally
{
Thread.Sleep(10000);
}
if (modem.Opened)
modem.Close();
port.Close();
Debug.Print("Thread End");
}
private ModemCommandStatus SendATCommand(string command, int maxWaitTime)
{
Debug.Print("Sending Command: " + command);
if (command != "+++")
command += "\r";
WriteToModem(command);
DateTime cmdExpiration = DateTime.Now.AddMilliseconds(maxWaitTime);
ModemCommandStatus modemResponse = ModemCommandStatus.Unknown;
byte[] readBuffer = new byte[0];
while (DateTime.Now < cmdExpiration)
{
Thread.Sleep(0);
if (port.BytesToRead > 0)
{
byte[] modemBuffer = new byte[port.BytesToRead];
int bytesRead = port.Read(modemBuffer, 0, modemBuffer.Length);
byte[] tempBuffer = new byte[readBuffer.Length];
Array.Copy(readBuffer, tempBuffer, readBuffer.Length);
readBuffer = new byte[tempBuffer.Length + modemBuffer.Length];
Array.Copy(tempBuffer, readBuffer, tempBuffer.Length);
Array.Copy(modemBuffer, 0, readBuffer, tempBuffer.Length, modemBuffer.Length);
modemResponse = GetResponse(ref readBuffer);
if (modemResponse != ModemCommandStatus.Unknown)
break;
}
}
Thread.Sleep(20);
string responseText = "UNKNOWN";
switch (modemResponse)
{
case ModemCommandStatus.Success:
responseText = "OK";
break;
case ModemCommandStatus.Connect:
responseText = "CONNECT";
break;
case ModemCommandStatus.NoCarrier:
responseText = "NO CARRIER";
break;
case ModemCommandStatus.Error:
responseText = "ERROR";
break;
}
Debug.Print("Modem Response: " + responseText);
return modemResponse;
}
private ModemCommandStatus GetResponse(ref byte[] data)
{
ModemCommandStatus status = ModemCommandStatus.Unknown;
if (FindMatch(data, new byte[] { 13, 10, 79, 75, 13, 10 }) > -1) //\r\nOK\r\n
{
status = ModemCommandStatus.Success;
}
else if (FindMatch(data, new byte[] { 13, 10, 69, 82, 82, 79, 82, 13, 10 }) > -1) //\r\nERROR\r\n
{
status = ModemCommandStatus.Error;
}
else if (FindMatch(data, new byte[] { 13, 10, 67, 79, 78, 78, 69, 67, 84 }) > -1) //\r\nCONNECT
{
status = ModemCommandStatus.Connect;
}
else if (FindMatch(data, new byte[] { 13, 10, 78, 79, 32, 67, 65, 82, 82, 73, 69, 82, 13, 10 }) > -1) //\r\nNO CARRIER\r\n
{
status = ModemCommandStatus.NoCarrier;
}
return status;
}
public int FindMatch(byte[] buffer, byte[] pattern)
{
if (buffer != null && pattern != null && buffer.Length != 0 && pattern.Length != 0 && pattern.Length <= buffer.Length)
{
int resumeIndex;
for (int i = 0; i <= buffer.Length - pattern.Length; i++)
{
if (buffer[i] == pattern[0])
{
resumeIndex = 0;
for (int x = 1; x < pattern.Length; x++)
{
if (buffer[i + x] == pattern[x])
{
if (x == pattern.Length - 1)
return i;
else if (resumeIndex == 0 && buffer[i + x] == pattern[0])
resumeIndex = i + x;
}
else
{
if (resumeIndex > 0)
i = resumeIndex - 1;
else if (x > 1)
i += (x - 1);
break;
}
}
}
}
}
return -1;
}
public enum ModemCommandStatus
{
Success,
Connect,
NoCarrier,
Error,
Unknown
}
private void WriteToModem(string command)
{
var sendBuffer = Encoding.UTF8.GetBytes(command);
port.Write(sendBuffer, 0, sendBuffer.Length);
}
private void HTTPRequest()
{
try
{
Debug.Print("Getting Host Entry for google.com...");
var dnsEntry = Dns.GetHostEntry("google.com");
Debug.Print(string.Concat("Host Entry: ", dnsEntry.AddressList[0].ToString()));
}
catch (Exception ex)
{
Debug.Print(string.Concat("Dns.GetHostEntry() Error: ", ex.ToString()));
}
}
private void LogException(Exception ex)
{
Debug.Print(ex.ToString());
if (ex.InnerException != null)
LogException(ex.InnerException);
}
}
}
Output when running from visual studio debugger:
[quote]Thread Start
Sending Command: ATE0
Modem Response: OK
Sending Command: AT+CSQ
Modem Response: OK
Sending Command: AT+CREG?
Modem Response: OK
Sending Command: ATD#777
Modem Response: CONNECT
Network Address Changed: 75.237.88.238
Network Available: True
Active Interface
Modem IP: 75.237.88.238
Modem Gateway: 66.174.179.228
Modem Mask: 255.255.255.0
Modem DHCP Enabled: True
Modem Dynamic DNS Enabled: False
Modem DNS 0: 208.67.222.222
Getting Host Entry for google.com…
Host Entry: 74.125.196.101
Sending Command: +++
Network Address Changed: 0.0.0.0
Network Available: False
Modem Response: UNKNOWN
Sending Command: ATH
Modem Response: OK
Sending Command: +++
Modem Response: UNKNOWN
Thread End[/quote]
Output when running the board without debugger but listening with MFDeploy:
[quote]Thread Start
Sending Command: ATE0
Modem Response: OK
Sending Command: AT+CSQ
Modem Response: OK
Sending Command: AT+CREG?
Modem Response: OK
Sending Command: ATD#777
Modem Response: CONNECT
Network Address Changed: 75.236.150.238
Network Available: True
Active Interface
Modem IP: 75.236.150.238
Modem Gateway: 66.174.179.228
Modem Mask: 255.255.255.0
Modem DHCP Enabled: True
Modem Dynamic DNS Enabled: False
Modem DNS 0: 198.224.152.119
Modem DNS 1: 198.224.154.135
Getting Host Entry for google.com…
#### Exception System.Net.Sockets.SocketException - CLR_E_FAIL (4) ####
#### Message:
#### Microsoft.SPOT.Net.SocketNative::getaddrinfo [IP: 0000] ####
#### System.Net.Dns::GetHostEntry [IP: 0008] ####
#### ModemTest.Program::HTTPRequest [IP: 000f] ####
#### ModemTest.Program::Work [IP: 014d] ####
#### SocketException ErrorCode = 10060
Dns.GetHostEntry() Error: System.Net.Sockets.SocketException
Sending Command: +++
Network Address Changed: 0.0.0.0
Network Available: False
Modem Response: UNKNOWN
Sending Command: ATH
Modem Response: OK
Sending Command: +++
Modem Response: UNKNOWN
Thread End[/quote]
I believe the framework bug is around the way the DNS logic is handled when debugging versus not. When I run the code with the visual studio debugger the DNS is reported as 208.67.222.222. This is an OpenDNS server and is not the value I proved when I set the static DNS entries. It looks like there may be something hardcoded in the framework and different code is executed when debugging than when not.