I picked up this awesome webserver from the Netduino forums - Another Web Server - Project Showcase - Netduino Forums
I’ve used it for years on Netduino projects. Recently I needed more RAM for my project and moved over to a G120.
I’ve had the PCB’s made and connected an ENC28 module successfully. It appears to be working except I can’t get a good webserver going. I keep running into this bug. https://www.ghielectronics.com/community/forum/topic?id=17222&page=1#msg171641
I can’t really be bothered with it and decided to re-use my old Netduino code. What I can’t figure out is how to “connect” this socket listener to my enc28 module.
here is the code I use to set up the enc28
class Setup
{
public static EthernetENC28J60 enc;
static bool hasAddress = false;
static bool available = false;
public static void Initilise()
{
NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;
NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;
enc = new GHI.Networking.EthernetENC28J60(SPI.SPI_module.SPI1,
GHI.Pins.G120.P1_10, // chip select
GHI.Pins.G120.P0_11, // interrupt
GHI.Pins.G120.P0_5 // reset
);
enc.Open();
enc.EnableStaticIP("10.0.0.100", "255.255.255.0", "10.0.0.1");
enc.EnableStaticDns(new string[] { "10.0.0.1" });
while (!hasAddress || !available)
{
Debug.Print("Initializing");
System.Threading.Thread.Sleep(100);
}
}
private static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
Debug.Print("Network available: " + e.IsAvailable.ToString());
available = e.IsAvailable;
}
private static void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
{
Debug.Print("The network address has changed.");
hasAddress = enc.IPAddress != "0.0.0.0";
Debug.Print(enc.IPAddress.ToString());
}
}
Here is the webserver code.
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using G120.Tools.FileManagement;
namespace G120.SAL.Eth
{
public delegate void WebRequest(Request request);
public class Server
{
public Server(int port, WebRequest userRequester)
{
using (System.Net.Sockets.Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
socket.Bind(new IPEndPoint(IPAddress.Any, port));
socket.Listen(10);
Log.Print("Http Server: Listening on address " + Detect.Eth_IP());
while (true)
{
try
{
using (Socket client = socket.Accept())
{
if (client.Poll(5000000, SelectMode.SelectRead))
{
if (client.Available > 0) new HttpRequester(client, userRequester);
}
}
}
catch { }
}
}
}
}
public class HttpRequester : IDisposable
{
const int bufLen = 512;
public void Dispose()
{
}
public object[] Arguments { get; set; }
public HttpRequester(Socket client, WebRequest userRequester)
{
using (client)
{
byte[] buffer = new byte[client.Available];
int count = client.Receive(buffer);
string s = new string(Encoding.UTF8.GetChars(buffer));
Request request = new Request(client, s);
string[] parts = request.url.Split('/');
string command = null;
string argument = null;
string values = null;
// Parse first part to command
if (parts.Length == 2)
{
command = parts[1].ToString();
}
if (parts.Length == 3)
{
command = parts[1].ToString();
argument = parts[2].ToString();
}
if (parts.Length == 4)
{
command = parts[1].ToString();
argument = parts[2].ToString();
values = parts[3].ToString();
}
if (userRequester != null) userRequester(request);
else
{ // this is skipped if userRequest is implemented
//if (request.url == "/") command = "menu";
switch (command)
{
case "test":
{
request.sendStream(new MemoryStream(Encoding.UTF8.GetBytes("You have shown a status blink of " + argument + " second.")));
Sally.StatusLED[1].Write(true);
Thread.Sleep(Convert.ToInt32(argument));
Sally.StatusLED[1].Write(false);
}
break;
case "/dir":
{
request.sendFileBrowser();
}
break;
case "log":
if (argument == "" || argument == null)
{
request.sendStream(new MemoryStream(Encoding.UTF8.GetBytes(/*Java.Refresh(10) + */"Most Recent on TOP<br /><br />" + Log.Read(0))));
//Log.Print("Memory: " + Microsoft.SPOT.Debug.GC(false).ToString());
}
else if (argument == "errors")
{
request.sendStream(new MemoryStream(Encoding.UTF8.GetBytes(/*Java.Refresh(10) + */"Most Recent on TOP<br /><br />" + Log.Read(1))));
}
else if (argument == "erase")
{
request.sendStream(new MemoryStream(Encoding.UTF8.GetBytes(/*Java.Refresh(10) + */"Most Recent on TOP<br /><br />" + Log.Read(0))));
Log.Erase(0);
Log.Erase(1);
}
else
{
request.sendStream(new MemoryStream(Encoding.UTF8.GetBytes(command.ToString() + " " + argument.ToString() + @ " is not a valid command. Try menu/index.html")));
}
break;
}
}
}
}
}
public class Request
{
public Socket client;
private string _url;
private string _argString;
private string[] _key;
private string[] _value;
public Request(Socket Client, string data)
{
client = Client;
if (data == null) data = "";
string[] parms = data.Trim().Split(' ');
string[] f = parms[1].Split('?');
_url = f[0].ToLower();
if (f.Length > 1) _argString = f[1].Trim(); else _argString = "";
_key = _argString.Split('&');
if (_key.Length == 1) if (_key[0] == "") _key = new string[0];
_value = new string[_key.Length];
for (int i = 0; i < _key.Length; i++)
{
string[] p = _key[i].Split('=');
if (p.Length > 1) _value[i] = p[1].Trim(); else _value[i] = "";
if (p.Length > 0) _key[i] = p[0].Trim().ToLower(); else _key[i] = "";
}
}
public string url { get { return _url; } set { _url = value; } }
public string path { get { return _url.toFullPath(); } set { _url = value.toUrl(); } }
public string[] key { get { return _key; } }
public string[] value { get { return _value; } }
public string getKey(string key)
{
for (int i = 0; i < _key.Length; i++) if (key.ToLower() == _key[i]) return value[i];
return "";
}
public string contextType
{
get
{
if (_url == "/") return "text/html";
switch (_url.Substring(_url.LastIndexOf('.') + 1).ToLower())
{
case "html":
case "htm": return "text/html";
case "css": return "text/css";
case "xml":
case "xsl": return "text/xml";
case "jpg":
case "jpeg": return "image/jpeg";
case "gif": return "image/gif";
case "json": return "application/json";
case "xhtml": return "application/xhtml+xml";
case "png": return "image/png";
case "ico": return "image/ico";
case "js": return "application/javascript";
case "gz":
case "zip": return "application/zip";
case "pdf": return "application/pdf";
case "mp3": return "audio/mpeg";
case "csv": return "text/csv";
case "txt":
default: return "text/plain";
}
}
}
const int bufLen = 512;
public void sendStream(Stream stream)
{
byte[] buffer = new byte[bufLen];
using (Stream inputStream = stream)
{
client.Send(Encoding.UTF8.GetBytes("HTTP/1.1 200 OK\r\nContent-Type: " + contextType + "; charset=utf-8\r\n" +
"Content-Length: " + inputStream.Length.ToString() + "\r\n" +
"\r\n" + "Connection: Close\r\n\r\n"));
while (true)
{
int bytesRead = inputStream.Read(buffer, 0, bufLen);
if (bytesRead == 0) break;
client.Send(buffer, bytesRead, SocketFlags.None);
Thread.Sleep(10);
}
}
}
public void sendFileBrowser()
{
string dir = getKey("dir").toFullPath();
msgStream sdr = new msgStream(this);
sdr.Write("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n");
sdr.Write("Connection: Close\r\n\r\n");
sdr.Write("<html><body><h2>Directory Browser: " + dir + "</h2><table style=\"font-family: 'Courier New', Courier, monospace; font-size: x-small\">");
sdr.Write("<tr><th align='left'>Name:</th><th align='right'></th><th></th></tr>");
if (!dir.isRoot())
sdr.Write("<tr><td><<a href='dir?dir=" + dir.Substring(0, dir.LastIndexOf('\\')).toUrl() + "'>../</a>></td><td></td><td></td></tr>");
DirectoryInfo di = new DirectoryInfo(dir);
DirectoryInfo[] disub = di.GetDirectories();
foreach (DirectoryInfo dii in disub) { sdr.Write("<tr><td><<a href='dir?dir=" + dii.FullName.toUrl() + "'>" + dii.Name + "</a>></td><td></td></tr>"); }
sdr.Write("<tr><th align='left'>Name:</th><th align='right'>Length:</th><th>Last modified:</th></tr>");
FileInfo[] rgFiles = di.GetFiles();
foreach (FileInfo fi in rgFiles) { sdr.Write("<tr><td><a href='" + fi.FullName.Substring(HttpHelper.SD_Root.Length) + "'>" + fi.Name + "</a></td><td align='right'>" + fi.Length + "</td><td>" + fi.LastWriteTime.ToString() + "</td></tr>"); }
sdr.Write("<tr><th align='left'>Build in:</th><th></th></tr>");
sdr.Write("<tr><td><a href=\"/\">Default page</a></td><td align='right'></td></tr>");
sdr.Write("<tr><td><a href=\"/fields.json\">Fields.JSON</a></td><td align='right'></td></tr>");
sdr.Write("</table></body></html>");
sdr.Flush();
}
public void sendFileNotFound()
{ // Send 404 - not found
client.Send(Encoding.UTF8.GetBytes("HTTP/1.1 404 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n" + "Connection: Close\r\n\r\n"));
}
public class msgStream
{
private string _buffer;
Request _request;
public msgStream(Request request)
{
_request = request;
_buffer = "";
}
public void Flush()
{
if (_buffer.Length > 0) _request.client.Send(Encoding.UTF8.GetBytes(_buffer));
_buffer = "";
}
public void Write(string buf)
{
_buffer += buf;
if (_buffer.Length > bufLen) Flush();
}
}
}
public static class HttpHelper
{
public const string SD_Root = @ "\SD\www";
public const int bufLen = 512;
public static string toFullPath(this string url)
{
string s = SD_Root.TrimEnd('\\') + '\\';
int p = 0;
if (p < url.Length) { if ((url[0] == '\\') | (url[0] == '/')) p++; }
while (p < url.Length)
{
if ((url[p] == '\\') | (url[p] == '/')) s += '\\'; else s += url[p];
p++;
}
return s;
}
public static string toUrl(this string path)
{
int p = SD_Root.TrimEnd('\\').Length;
string s = "";
while (p < path.Length)
{
if (path[p] == '\\') s += '/'; else s += path[p];
p++;
}
return s;
}
public static bool isRoot(this string path)
{
return (path == (SD_Root.TrimEnd('\\') + '\\'));
}
}
}