#include <SPI.h>
#include <Ethernet.h>
#include <utility/socket.h>
#include <EtherRaw.h>
#include <RF22Datagram.h>
#include <RF22.h>
#define THIS_ADDRESS 1
MACAddress mac(0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED);
IPAddress ip(203, 63, 154, 101);
IPv4Address defaultReplyAddress(203, 63, 154, 29);
uint16_t defaultReplyPort = 9048;
uint8_t macraw_socket = 0;
uint8_t udp_reply_socket = 1;
void setup()
{
delay(100);
Ethernet.begin(mac.address(), ip);
Serial.begin(115200);
socket(macraw_socket, SnMR::MACRAW, 0, 0);
if (!rf22.init())
Serial.println("RF22 init failed");
}
uint16_t macraw_read(SOCKET s, uint8_t *buf, uint16_t len)
{
uint8_t head[2];
uint16_t data_len=0;
uint16_t ptr=0;
if (!W5100.getRXReceivedSize(s))
return 0;
ptr = W5100.readSnRX_RD(s);
W5100.read_data(s, (uint8_t*)ptr, head, 2);
ptr+=2;
data_len = head[0];
data_len = (data_len<<8) + head[1] - 2;
if (len > data_len)
len = data_len;
W5100.read_data(s, (uint8_t*)ptr, buf, len);
ptr += data_len;
W5100.writeSnRX_RD(s, ptr);
W5100.execCmdSn(s, Sock_RECV);
return len;
}
typedef struct Source
{
IPv4Address source;
uint16_t sourcePort;
uint16_t destPort;
} Source;
#define NUM_SOURCE_RECORDS 4
Source sources[NUM_SOURCE_RECORDS];
uint8_t next_source_record = 0;
struct Source* findSourceRecord(uint16_t destPort)
{
uint8_t i;
for (i =0; i < NUM_SOURCE_RECORDS; i++)
{
if (sources[i].destPort == destPort)
return &sources[i];
}
return NULL;
}
void recordSource(const IPv4Address& source, uint16_t sourcePort, uint16_t destPort)
{
Source* s = findSourceRecord(destPort);
if (!s)
{
s = &sources[next_source_record];
next_source_record = (next_source_record + 1) % NUM_SOURCE_RECORDS;
}
s->source = source;
s->sourcePort = sourcePort;
s->destPort = destPort;
}
void loop()
{
uint16_t len;
uint8_t buf[200];
cli();
len = macraw_read(macraw_socket, buf, sizeof(buf));
sei();
if (len)
{
EthernetHeader* h = (EthernetHeader*)buf;
if (!(h->dest() == mac))
return;
if (h->ethertype() != EthernetHeader::ETH_P_IP)
return;
PacketIPv4* p = (PacketIPv4*)h->payload();
if (p->version() != IPVERSION)
return;
if (!(ip == p->dest().address()))
return;
if (p->protocol() != PacketIPv4::IPPROTO_UDP)
return;
PacketUDP* u = (PacketUDP*)p->payload();
if (u->destPort() != THIS_ADDRESS)
{
recordSource(p->source(), u->sourcePort(), u->destPort());
if (rf22.sendto(u->payload(), u->payload_length(), u->destPort()))
rf22.waitPacketSent();
}
}
uint8_t recvlen = sizeof(buf);
uint8_t from;
uint8_t to;
if (rf22.recvfrom(buf, &recvlen, &from, &to))
{
cli();
socket(udp_reply_socket, SnMR::UDP, from, 0);
Source* s = findSourceRecord(from);
if (s)
sendto(udp_reply_socket, buf, recvlen, (uint8_t*)s->source.address(), s->sourcePort);
else
sendto(udp_reply_socket, buf, recvlen, (uint8_t*)defaultReplyAddress.address(), defaultReplyPort);
close(udp_reply_socket);
sei();
}
}