Networking-for-Arduino / EthernetENC

Ethernet library for ENC28J60. This is a modern version of the UIPEthernet library. EthernetENC library is compatible with all Arduino architectures with Arduino SPI library with transactions support. Only include EthernetENC.h instead of Ethernet.h
127 stars 28 forks source link

Not receiving UDP responses #14

Closed niallfleming closed 3 years ago

niallfleming commented 3 years ago

This is the not the code I want to run, but I was trying to attack it from another angle.

This is being run on a nano with an enc28j60 ethernet shield. I receive the udp message to the serial console as expected, but the client never receives the ack in response. local firewall is disabled.

I confirmed that the theory works with a python version, in case it was netcat being weird, but it behaved the way I expected, I sent text, and I received it back.

Here's my test code, ultimately I'm trying to work out why I wasn't seeing the subscription coming back from the nano to my ArtNet server. I tried removing the line suggested in #3 in case it was a similar thing, but no dice.

#include <EthernetENC.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

uint8_t mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x78, 0xEE };
IPAddress ip(192,168,0,115);
//byte ip[] = {192,168,0,115};
unsigned int localPort = 6454;

// buffers for receiving and sending data
char packetBuffer[800];  // buffer to hold incoming packet,
char ReplyBuffer[] = "ack";        // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  Serial.begin(115200);
  //while (!Serial) {
  //  ; // wait for serial port to connect. Needed for native USB port only
  //}
  Ethernet.begin(mac, ip);
  //Serial.println(Ethernet.localIP());
  Udp.begin(localPort);
}

void loop() {
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print(F("Received packet of size "));
    Serial.println(packetSize);
    Serial.print(F("From "));
    IPAddress remote = Udp.remoteIP();
    for (int i=0; i < 4; i++) {
      Serial.print(remote[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }
    Serial.print(F(", port "));
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer, 800);
    Serial.println(F("Contents:"));
    Serial.println(packetBuffer);

    // send a reply to the IP address and port that sent us the packet we received
    Serial.println(Udp.remoteIP());
    Serial.println(Udp.remotePort());
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Serial.println(ReplyBuffer);
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}
JAndrassy commented 3 years ago

does the other side send on the same port as it expects the response? try to send the replay to constant port number instead of Udp.remotePort()

niallfleming commented 3 years ago

Like this?

    Udp.beginPacket(Udp.remoteIP(), 6454); //Udp.remotePort()
    Serial.println(ReplyBuffer);
    Udp.write(ReplyBuffer);
    Udp.endPacket();

Same behaviour.

niallfleming commented 3 years ago

OK so it was related to line endings in the library. Once I had eradicated all the ^M dos line endings it seems to work with the original code.

Can you say why I don't see any serial console prints from the library - I defined

#define UIPETHERNET_DEBUG_UDP 1

prior to including EthernetENC and so on?

JAndrassy commented 3 years ago

include is replaced with the content of the included file so the define doesn't apply to other occurrences of including the same .h

niallfleming commented 3 years ago

Oh I see. Thanks.

So I've got further, I want it to listen on the broadcast (network address) as well as it's own IP, it does respond on unicast, but that's not what I need in this situation. I see that you're limiting broadcast to ARP in Enc28J60Network.cpp

  // For broadcast packets we allow only ARP packtets
  // All other packets should be unicast only for our mac (MAADR)

Is there a way to override this behaviour? I presume that there is too much broadcast traffic so it was limited for this reason? -- ArtNet packets are defined here: https://art-net.org.uk/how-it-works/streaming-packets/artdmx-packet-definition/

Here's a trace of the packet emitted from the controller (Mac) to the broadcast address:

    192.168.0.104.6454 > 192.168.0.255.6454: [udp sum ok] UDP, length 530
    0x0000:  4500 022e 6204 0000 4011 9403 c0a8 0068  E...b...@......h
    0x0010:  c0a8 00ff 1936 1936 021a 9d31 4172 742d  .....6.6...1Art-
    0x0020:  4e65 7400 0050 000e 3000 0000 0200 ffff  Net..P..0.......
    0x0030:  ffff ffff ffff ffff ffff ffff ff00 0000  ................
    0x0040:  0000 0000 0000 0000 0000 0000 0000 0000  ................
    0x0050:  0000 0000 0000 0000 0000 0000 0000 0000  ................
    0x0060:  0000 0000 0000 0000 0000 0000 0000 0000  ................
    0x0070:  0000 0000 0000 0000 0000 0000 0000 0000  ................
    0x0080:  0000 0000 0000 0000 0000 0000 0000 0000  ................
JAndrassy commented 3 years ago

size of the receive buffer is only 2 kB. to process broadcast every broadcast packet must be stored to receive buffer and then handled by the library. the library handles the packets by default every 100 milliseconds (only if some library function is called).

you can enable receiving of broadcast packages in Enc28J60Network.cpp

writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN);