G120 4.2.11.2 ENC28 1ARP request return 2ARP responses

@ GHI… Sending a file from a web browser fails.

Description of the setup:

  1. Having a httplisteren running on CobraII
  2. On a Win7/32 PC, from a web browser posting a file.
    Both devices are connected to a network switch. Switch connected to a Router.

After the PC have send a number of HTTP/TCP packets it sends an ARP request to G120. G120 replies with 2 ARP responses.
The next packet send by PC is a TCP re-transmit and finaly a RESET package.

Then browser times-out "web-page not available"
This is consistent behaviour.

Having a laptop Win7/32 connected 1:1 with a cross cable to the cobra works fine.
I don’t see any ARP request

BTW … See many many TCP re-transmits in both setup’s

@ RobvanSchelven -

Can you help us 3 things:

  • Is it happened with earlier version?
  • Is it happened with wifi?
  • Can you write small example (For Corba II and PC) that help us to see the problem quickly, please?

@ Dat - I went back to 4.2.11.0 from last august and see the same problem
Haven’t tested with WiFi since this project is only using wired Ethernet.
I will email you directly ASAP with a test program.

@ Dat - I have send you 2 VS2010 solutions to test. For others interested… see below:

Win32 console code, used to send data to cobra


using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

// references needed
// System
// System.Core

// 2014 March 01 : Win32 console utility of HTTP post code to demonstrate a number of issues on CobraII

// Make sure IP address on device is same as used below her (192.168.0.130)

namespace WinSockSend
{
    internal class Program
    {
        private static void Main()
        {
            Console.WriteLine("Socket send test utility. Press any key to stop.");
            using (var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                clientSocket.SendBufferSize = 1460;
                var r = new Random();
                try
                {
                    clientSocket.Connect("192.168.0.130", 80);

                    SendDummyHTTPHeader(clientSocket);

                    var ioBuffer = new byte[1460];
                    while (true)
                    {
                        var b = (byte) r.Next(255);
                        for (int i = 0; i < 1460; i++)
                        {
                            ioBuffer[i] = b;
                        }
                        SocketWrite(clientSocket, ioBuffer, ioBuffer.Length);
                        if (Console.KeyAvailable)
                        {
                            while (Console.KeyAvailable)
                            {
                                Console.ReadKey();
                            }
                            clientSocket.Close();
                            return;
                        }
                    }
                }

                catch (Exception exception)
                {
                    Console.WriteLine(exception.Message);
                    clientSocket.Close();
                }
            }
        }

        private static void SendDummyHTTPHeader(Socket clientSocket)
        {
            // obtain ip address of the computer we run this test code
            // ip is 'neccesary' to put in the http request header
            string thisTestMachineIP = "";
            IPAddress[] ipaddressen = Dns.GetHostAddresses(Dns.GetHostName());
            foreach (IPAddress ip in ipaddressen)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    thisTestMachineIP = ip.ToString();
                    break;
                }
            }

            // Create an HTTP request header
            var sb = new StringBuilder();
            // sb.Append("POST http://192.168.0.130:8000/upload.cgi HTTP/1.1\n"); // when using http port 8000 instead of 80
            sb.Append("POST /upload.cgi HTTP/1.1\n");                             // when using default http port 80

            sb.Append("Host: 192.168.0.130\n");
            sb.Append("Content-Length: 1000000\n");
            sb.Append("Origin: http://" + thisTestMachineIP + "\n");
            sb.Append("User-Agent: Schedulon Music File Upload Utility V1.0\n");
            sb.Append("Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1Z4ZlNEzO4kVBBwY\n");
            sb.Append("Referer: http://" + thisTestMachineIP + "\n");
            sb.Append("\n");
            sb.Append("------WebKitFormBoundary1Z4ZlNEzO4kVBBwY\n");
            sb.Append("Content-Disposition: form-data; name=\"datafile\"; filename=\"testfile.mp3\n");
            sb.Append("Content-Type: application/x-msdownload\r\n\r\n");

            byte[] buffer = Encoding.UTF8.GetBytes(sb.ToString());
            SocketWrite(clientSocket, buffer, buffer.Length);
        }

        private static void SocketWrite(Socket socket, byte[] ioBuffer, int length)
        {
            int written = 0;
            do
            {
                written += socket.Send(ioBuffer, written, length - written, SocketFlags.None);
                if (Console.KeyAvailable)
                    return;
            } while (written < length);
        }
    }
}

Code running on Cobra II with external ENC28 and SD card


using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using GHI.Hardware.G120;
using GHI.Premium.IO;
using GHI.Premium.Net;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

// References needed
// GHI.Hardware.G120
// GHI.Premium.IO
// GHI.Premium.Net
// GHI.Premium.System
// Microsoft.SPOT.Hardware
// Microsoft.SPOT.Native
// Microsoft.SPOT.Net
// mscorlib
// System
// System.Http
// System.IO

// 2014 March 01 : HTTP server demo code to demonstrate a number of issues
// Hardware: COBRA II with external ENC28 v1.1 ethernet module and Sandisk Extreme pro 8GB sd card
// Fimrmware 4.2.11.2
// Dev. Environment: Win7/32 VS2010

namespace CobraIISockReceive
{
    public class Program
    {
        private static EthernetENC28J60 _nic;
        private static HttpListener _listener;
        private static PersistentStorage _storage;

        public static void Main()
        {
            // Setup Storage
            try
            {
                _storage = new PersistentStorage("SD");
                _storage.MountFileSystem();
            }
            catch
            {
                Debug.Print("No SD Card");
                Thread.Sleep(Timeout.Infinite);
            }

            // Setup network
            _nic = new EthernetENC28J60(SPI.SPI_module.SPI1, Pin.P1_5, Pin.P0_1, Pin.P0_10);
            if (!_nic.IsOpen)
                _nic.Open();

            NetworkInterfaceExtension.AssignNetworkingStackTo(_nic);
            _nic.NetworkInterface.EnableStaticDns(new[] {"8.8.8.8", "8.8.4.4"});
            _nic.NetworkInterface.EnableStaticIP("192.168.0.130", "192.168.0.1", "255.255.255.0");

            while (Equals(IPAddress.GetDefaultLocalAddress(), IPAddress.Any))
            {
                Debug.Print("IP address is not set yet.");
                Thread.Sleep(25);
            }

            // create a target file directory if not exist
            if (!Directory.Exists(@ "\SD\Media"))
                Directory.CreateDirectory(@ "\SD\Media");

            RunHTTPServer();
        }

        private static void RunHTTPServer()
        {
            _listener = new HttpListener("http", 80) {MaximumResponseHeadersLength = 10};
            _listener.Start();
            while (true)
            {
                try
                {
                    HttpListenerContext ctx = _listener.GetContext();

                    if (ctx != null)
                    {
                        /*
                        object clientInputStream =
                            typeof (HttpListenerContext).GetField("m_clientInputStream", BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance).GetValue(ctx);
                        Type cist = clientInputStream.GetType();
                        var t = (Socket) cist.GetField("m_Socket", BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance).GetValue(clientInputStream);

                        t.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
                        t.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
                        t.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.ReuseAddress, true);
                        */
                        HandleRequest(ctx);
                    }
                    else
                    {
                        Debug.Print("HttpListenerContext = NULL");
                    }
                }
                catch (SocketException socketException)
                {
                    Debug.Print("Socket Error: " + socketException.ErrorCode);
                    switch (socketException.ErrorCode)
                    {
                        case 10050: // network down (happens when cable removed) **
                        case 10051: // network unreachable
                            _listener.Close();
                            return;

                        case 10052: // network dropped connection on reset
                        case 10053: // software caused connection abord 
                        case 10054: // connection reset by peer ( happens when browser shutsdown or refresh) **
                            break;
                    }
                }

                catch (Exception)
                {
                    _listener.Close();
                    return;
                }
            }
        }


        private static void HandleRequest(HttpListenerContext ctx)
        {
            var r = new Random(); // used for random filename generator
            FileStream outPutFileStream = null; // used to write data to SD card

            try
            {
                // Create a file with random name
                // @ GHI : Sometime CLR_IO_ERROR(1) ????
                outPutFileStream = new FileStream(@ "SD\Media\datadump" + r.Next() + ".bin", FileMode.Create);
                Debug.Print(outPutFileStream.Name);

                // @ GHI : using a http port other as 80 for example 8000 genereates an System.Net.ProtocolViolationException : See comments at the end of this file
                // this actually not the problem i wanted to demonstrate here, but came accros this
                HttpListenerRequest request = ctx.Request;

                const int bufferLength = 1460; // our test length
                var inputData = new byte[bufferLength]; // buffer for received data
                long totRead = 0; // total read counter, just for debugging

                // loop receiving bytes and write them to file
                while (true)
                {
                    int read = request.InputStream.Read(inputData, 0, bufferLength);
                    if (read == 0)
                    {
                        Debug.Print("Connection gone...Length 0");
                        break;
                    }
                    // @ GHI : Somtimes after receiving 32767 bytes the write generates an exception (See below)
                    outPutFileStream.Write(inputData, 0, bufferLength);
                    totRead += read;
                    Debug.Print(totRead.ToString());
                }
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }

            finally
            {
                ctx.Response.Close();
                if (outPutFileStream != null)
                {
                    outPutFileStream.Close();
                    outPutFileStream.Dispose();
                }
            }
        }
    }
}

/*
26435
27895
29355
30815
    #### Exception System.IO.IOException - CLR_E_FILE_IO (1) ####
    #### Message: 
    #### Microsoft.SPOT.IO.NativeFileStream::Write [IP: 0000] ####
    #### System.IO.FileStream::Write [IP: 002a] ####
    #### CobraIISockReceive.Program::HandleRequest [IP: 006d] ####
    #### CobraIISockReceive.Program::Run [IP: 0035] ####
    #### CobraIISockReceive.Program::Main [IP: 00a2] ####
A first chance exception of type 'System.IO.IOException' occurred in Microsoft.SPOT.IO.dll
Exception was thrown: System.IO.IOException
*/

/*
 #### Exception System.Net.ProtocolViolationException - 0x00000000 (1) ####
    #### Message: Unsupported HTTP version: HTTP/1.
    #### System.Net.HttpListenerRequest::ParseHTTPRequest [IP: 0084] ####
    #### System.Net.HttpListenerContext::get_Request [IP: 000d] ####
    #### CobraIISockReceive.Program::RunHTTPServer [IP: 0038] ####
    #### CobraIISockReceive.Program::Main [IP: 00b1] ####
*/

@ RobvanSchelven -

yes, thank
we will follow these to reproduce

@ Dat - Looking forward for your results / comments.

@ Dat - Already any comments?

Not yet
:smiley:

Our team just got confirmation from our lead to starting on this today, we were busy before.
(We know you raised this issue few days ago :slight_smile: )

@ RobvanSchelven - We have just responded to your email with a work-around, but are posting it for the public as well.

The issue of transmission abruptly ending can be fixed with the work around described here: https://www.ghielectronics.com/community/forum/topic?id=14851&page=1#msg151083

It seems that the buffer is becoming overfilled without tossing the context into a separate thread.

We were not able to reproduce the ARP issue (Please see attachment). I would first try this with a different router as duplicate packets can also be caused by a failing switch.

@ James - Thanks for your message. I replied to your email. It is unlikely that is has much to do with my switch since the problem happens in the field too with total different network setup’s and different routers.

Update: I have emailed a winshark capture file of a failed upload.

@ GHI Any intermediate update?

@ GHI :think: ? ? ?

Sorry for the delay, I’ve been waiting for James to return from out of town as he was the member of the team that was working on this issue.

Given the complexity of the hardware and the associated software stack, it is unlikely that James could diagnose the issue from a dump/trace in any reasonable amount of time. We appreciated your providing the smaller program; as I communicated in email, we were unable to observe the ARP transactions and/or the timeout regards the TCP exchange. If you can give us instructions on how you recreated the problem with the test application it would be a big help.

I’ll give you an update tomorrow.