Add new scene controller with touch display example.
Upgraded RF24 to latest version which supports SoftSPI. Added DigitalIO and UTFT libraries to support the new example. Fix problem reported in RelayWithButtonActuator example.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
This is UIPEthernet version 1.01
|
||||
This is UIPEthernet version 1.07
|
||||
|
||||
An plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields and breakout boards. Full support for persistent (streaming) TCP-connections and UDP (Client and Server each), ARP, ICMP, DHCP and DNS.
|
||||
Just include 'UIPEthernet.h' instead of 'Ethernet.h' and use all your code written for the stock Arduino Ethernet lib!
|
||||
@@ -26,7 +26,9 @@ On a Mac, you will want to create a folder named "libraries" in in the "Document
|
||||
$ cd ~/Documents/Arduino/libraries
|
||||
$ git clone https://github.com/ntruchsess/arduino_uip UIPEthernet
|
||||
|
||||
Or you download the zipped version of the library from https://github.com/ntruchsess/arduino_uip/archive/master.zip, create a directory [path to Arduino distribution]\libraries\UIPEthernet and put the contents of the zip-file there.
|
||||
Or you download the zipped version of the library from https://github.com/ntruchsess/arduino_uip/releases, and copy the contained directory UIPEthernet to [path to Arduino distribution]\libraries\UIPEthernet.
|
||||
|
||||
If you are running Arduino-IDE 1.5.x use release-version 1.57 or checkout branch 'Arduino_1.5.5'
|
||||
|
||||
Additional information can be found on the Arduino website: http://www.arduino.cc/en/Hacking/Libraries
|
||||
|
||||
|
||||
+152
-104
@@ -49,19 +49,22 @@ UIPClient::UIPClient(uip_userdata_t* conn_data) :
|
||||
int
|
||||
UIPClient::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
stop();
|
||||
uip_ipaddr_t ipaddr;
|
||||
uip_ip_addr(ipaddr, ip);
|
||||
struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
|
||||
if (conn)
|
||||
{
|
||||
#if UIP_CONNECT_TIMEOUT > 0
|
||||
int32_t timeout = millis() + 1000 * UIP_CONNECT_TIMEOUT;
|
||||
#endif
|
||||
while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
UIPEthernetClass::tick();
|
||||
if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
|
||||
{
|
||||
data = (uip_userdata_t*) conn->appstate;
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
|
||||
Serial.print(F("connected, state: "));
|
||||
Serial.print(data->state);
|
||||
Serial.print(F(", first packet in: "));
|
||||
@@ -69,6 +72,13 @@ UIPClient::connect(IPAddress ip, uint16_t port)
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
#if UIP_CONNECT_TIMEOUT > 0
|
||||
if (((int32_t)(millis() - timeout)) > 0)
|
||||
{
|
||||
conn->tcpstateflags = UIP_CLOSED;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -83,7 +93,7 @@ UIPClient::connect(const char *host, uint16_t port)
|
||||
DNSClient dns;
|
||||
IPAddress remote_addr;
|
||||
|
||||
dns.begin(UIPEthernet.dnsServerIP());
|
||||
dns.begin(UIPEthernetClass::_dnsServerAddress);
|
||||
ret = dns.getHostByName(host, remote_addr);
|
||||
if (ret == 1) {
|
||||
return connect(remote_addr, port);
|
||||
@@ -95,10 +105,14 @@ UIPClient::connect(const char *host, uint16_t port)
|
||||
void
|
||||
UIPClient::stop()
|
||||
{
|
||||
if (data)
|
||||
if (data && data->state)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("before stop(), with data"));
|
||||
_dumpAllData();
|
||||
#endif
|
||||
_flushBlocks(&data->packets_in[0]);
|
||||
if (data->state & UIP_CLIENT_CLOSED)
|
||||
if (data->state & UIP_CLIENT_REMOTECLOSED)
|
||||
{
|
||||
data->state = 0;
|
||||
}
|
||||
@@ -106,9 +120,19 @@ UIPClient::stop()
|
||||
{
|
||||
data->state |= UIP_CLIENT_CLOSE;
|
||||
}
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("after stop()"));
|
||||
_dumpAllData();
|
||||
#endif
|
||||
}
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
else
|
||||
{
|
||||
Serial.println(F("stop(), data: NULL"));
|
||||
}
|
||||
#endif
|
||||
data = NULL;
|
||||
UIPEthernet.tick();
|
||||
UIPEthernetClass::tick();
|
||||
}
|
||||
|
||||
uint8_t
|
||||
@@ -125,8 +149,8 @@ UIPClient::operator==(const UIPClient& rhs)
|
||||
|
||||
UIPClient::operator bool()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
return data && (!(data->state & UIP_CLIENT_CLOSED) || data->packets_in[0] != NOBLOCK);
|
||||
UIPEthernetClass::tick();
|
||||
return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in[0] != NOBLOCK);
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -150,15 +174,15 @@ UIPClient::_write(uip_userdata_t* u, const uint8_t *buf, size_t size)
|
||||
uint16_t attempts = UIP_ATTEMPTS_ON_WRITE;
|
||||
#endif
|
||||
repeat:
|
||||
UIPEthernet.tick();
|
||||
if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED)))
|
||||
UIPEthernetClass::tick();
|
||||
if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
|
||||
{
|
||||
memhandle* p = _currentBlock(&u->packets_out[0]);
|
||||
if (*p == NOBLOCK)
|
||||
uint8_t p = _currentBlock(&u->packets_out[0]);
|
||||
if (u->packets_out[p] == NOBLOCK)
|
||||
{
|
||||
newpacket:
|
||||
*p = UIPEthernet.network.allocBlock(UIP_SOCKET_DATALEN);
|
||||
if (*p == NOBLOCK)
|
||||
u->packets_out[p] = Enc28J60Network::allocBlock(UIP_SOCKET_DATALEN);
|
||||
if (u->packets_out[p] == NOBLOCK)
|
||||
{
|
||||
#if UIP_ATTEMPTS_ON_WRITE > 0
|
||||
if ((--attempts)>0)
|
||||
@@ -172,7 +196,7 @@ newpacket:
|
||||
}
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.print(F("UIPClient.write: writePacket("));
|
||||
Serial.print(*p);
|
||||
Serial.print(u->packets_out[p]);
|
||||
Serial.print(F(") pos: "));
|
||||
Serial.print(u->out_pos);
|
||||
Serial.print(F(", buf["));
|
||||
@@ -183,12 +207,12 @@ newpacket:
|
||||
Serial.write((uint8_t*)buf+size-remain,remain);
|
||||
Serial.println(F("'"));
|
||||
#endif
|
||||
written = UIPEthernet.network.writePacket(*p,u->out_pos,(uint8_t*)buf+size-remain,remain);
|
||||
written = Enc28J60Network::writePacket(u->packets_out[p],u->out_pos,(uint8_t*)buf+size-remain,remain);
|
||||
remain -= written;
|
||||
u->out_pos+=written;
|
||||
if (remain > 0)
|
||||
{
|
||||
if (p==&u->packets_out[UIP_SOCKET_NUMPACKETS-1])
|
||||
if (p == UIP_SOCKET_NUMPACKETS-1)
|
||||
{
|
||||
#if UIP_ATTEMPTS_ON_WRITE > 0
|
||||
if ((--attempts)>0)
|
||||
@@ -218,15 +242,10 @@ UIPClient::available()
|
||||
int
|
||||
UIPClient::_available(uip_userdata_t *u)
|
||||
{
|
||||
memhandle* p = &u->packets_in[0];
|
||||
if (*p == NOBLOCK)
|
||||
return 0;
|
||||
int len = 0;
|
||||
for(memhandle* end = p+UIP_SOCKET_NUMPACKETS; p < end; p++)
|
||||
for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++)
|
||||
{
|
||||
if(*p == NOBLOCK)
|
||||
break;
|
||||
len += UIPEthernet.network.blockSize(*p);
|
||||
len += Enc28J60Network::blockSize(u->packets_in[i]);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
@@ -236,23 +255,22 @@ UIPClient::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
if (*this)
|
||||
{
|
||||
int remain = size;
|
||||
memhandle* p = &data->packets_in[0];
|
||||
if (*p == NOBLOCK)
|
||||
uint16_t remain = size;
|
||||
if (data->packets_in[0] == NOBLOCK)
|
||||
return 0;
|
||||
int read;
|
||||
uint16_t read;
|
||||
do
|
||||
{
|
||||
read = UIPEthernet.network.readPacket(*p,0,buf+size-remain,remain);
|
||||
if (read == UIPEthernet.network.blockSize(*p))
|
||||
read = Enc28J60Network::readPacket(data->packets_in[0],0,buf+size-remain,remain);
|
||||
if (read == Enc28J60Network::blockSize(data->packets_in[0]))
|
||||
{
|
||||
remain -= read;
|
||||
_eatBlock(p);
|
||||
if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED)))
|
||||
_eatBlock(&data->packets_in[0]);
|
||||
if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
|
||||
data->state |= UIP_CLIENT_RESTART;
|
||||
if (*p == NOBLOCK)
|
||||
if (data->packets_in[0] == NOBLOCK)
|
||||
{
|
||||
if (data->state & UIP_CLIENT_CLOSED)
|
||||
if (data->state & UIP_CLIENT_REMOTECLOSED)
|
||||
{
|
||||
data->state = 0;
|
||||
data = NULL;
|
||||
@@ -262,7 +280,7 @@ UIPClient::read(uint8_t *buf, size_t size)
|
||||
}
|
||||
else
|
||||
{
|
||||
UIPEthernet.network.resizeBlock(*p,read);
|
||||
Enc28J60Network::resizeBlock(data->packets_in[0],read);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -286,11 +304,10 @@ UIPClient::peek()
|
||||
{
|
||||
if (*this)
|
||||
{
|
||||
memhandle p = data->packets_in[0];
|
||||
if (p != NOBLOCK)
|
||||
if (data->packets_in[0] != NOBLOCK)
|
||||
{
|
||||
uint8_t c;
|
||||
UIPEthernet.network.readPacket(p,0,&c,1);
|
||||
Enc28J60Network::readPacket(data->packets_in[0],0,&c,1);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
@@ -308,26 +325,21 @@ UIPClient::flush()
|
||||
|
||||
void
|
||||
uipclient_appcall(void)
|
||||
{
|
||||
UIPClient::uip_callback();
|
||||
}
|
||||
|
||||
void
|
||||
UIPClient::uip_callback()
|
||||
{
|
||||
uip_userdata_t *u = (uip_userdata_t*)uip_conn->appstate;
|
||||
if (!u && uip_connected())
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("UIPClient uip_connected"));
|
||||
UIPClient::_dumpAllData();
|
||||
#endif
|
||||
u = (uip_userdata_t*) _allocateData();
|
||||
u = (uip_userdata_t*) UIPClient::_allocateData();
|
||||
if (u)
|
||||
{
|
||||
uip_conn->appstate = u;
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.print(F("UIPClient allocated state: "));
|
||||
Serial.println(u->state);
|
||||
Serial.println(u->state,BIN);
|
||||
#endif
|
||||
}
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
@@ -343,33 +355,24 @@ UIPClient::uip_callback()
|
||||
Serial.print(F("UIPClient uip_newdata, uip_len:"));
|
||||
Serial.println(uip_len);
|
||||
#endif
|
||||
if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED)))
|
||||
if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
|
||||
{
|
||||
memhandle newPacket = UIPEthernet.network.allocBlock(uip_len);
|
||||
memhandle newPacket = Enc28J60Network::allocBlock(uip_len);
|
||||
if (newPacket != NOBLOCK)
|
||||
{
|
||||
memhandle* p = _currentBlock(&u->packets_in[0]);
|
||||
//if it's not the first packet
|
||||
if (*p != NOBLOCK)
|
||||
for (uint8_t i=0; i < UIP_SOCKET_NUMPACKETS; i++)
|
||||
{
|
||||
uint8_t slot = p - &u->packets_in[0];
|
||||
if (slot < UIP_SOCKET_NUMPACKETS-1)
|
||||
p++;
|
||||
//if this is the last slot stop this connection
|
||||
if (slot >= UIP_SOCKET_NUMPACKETS-2)
|
||||
if (u->packets_in[i] == NOBLOCK)
|
||||
{
|
||||
uip_stop();
|
||||
//if there's no free slot left omit loosing this packet and (again) stop this connection
|
||||
if (slot == UIP_SOCKET_NUMPACKETS-1)
|
||||
goto reject_newdata;
|
||||
if (i == UIP_SOCKET_NUMPACKETS-1)
|
||||
uip_stop();
|
||||
Enc28J60Network::copyPacket(newPacket,0,UIPEthernetClass::in_packet,((uint8_t*)uip_appdata)-uip_buf,uip_len);
|
||||
u->packets_in[i] = newPacket;
|
||||
goto finish_newdata;
|
||||
}
|
||||
}
|
||||
UIPEthernet.network.copyPacket(newPacket,0,UIPEthernet.in_packet,((uint8_t*)uip_appdata)-uip_buf,uip_len);
|
||||
*p = newPacket;
|
||||
goto finish_newdata;
|
||||
}
|
||||
reject_newdata:
|
||||
UIPEthernet.packetstate &= ~UIPETHERNET_FREEPACKET;
|
||||
UIPEthernetClass::packetstate &= ~UIPETHERNET_FREEPACKET;
|
||||
uip_stop();
|
||||
}
|
||||
}
|
||||
@@ -384,17 +387,22 @@ finish_newdata:
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("UIPClient uip_closed"));
|
||||
UIPClient::_dumpAllData();
|
||||
#endif
|
||||
// drop outgoing packets not sent yet:
|
||||
_flushBlocks(&u->packets_out[0]);
|
||||
UIPClient::_flushBlocks(&u->packets_out[0]);
|
||||
if (u->packets_in[0] != NOBLOCK)
|
||||
{
|
||||
((uip_userdata_closed_t *)u)->lport = uip_conn->lport;
|
||||
u->state |= UIP_CLIENT_CLOSED;
|
||||
u->state |= UIP_CLIENT_REMOTECLOSED;
|
||||
}
|
||||
else
|
||||
u->state = 0;
|
||||
// disassociate appdata.
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("after UIPClient uip_closed"));
|
||||
UIPClient::_dumpAllData();
|
||||
#endif
|
||||
uip_conn->appstate = NULL;
|
||||
goto nodata;
|
||||
}
|
||||
@@ -403,34 +411,33 @@ finish_newdata:
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("UIPClient uip_acked"));
|
||||
#endif
|
||||
_eatBlock(&u->packets_out[0]);
|
||||
UIPClient::_eatBlock(&u->packets_out[0]);
|
||||
}
|
||||
if (uip_poll() || uip_rexmit())
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
//Serial.println(F("UIPClient uip_poll"));
|
||||
#endif
|
||||
memhandle p = u->packets_out[0];
|
||||
if (p != NOBLOCK)
|
||||
if (u->packets_out[0] != NOBLOCK)
|
||||
{
|
||||
if (u->packets_out[1] == NOBLOCK)
|
||||
{
|
||||
uip_len = u->out_pos;
|
||||
if (uip_len > 0)
|
||||
{
|
||||
UIPEthernet.network.resizeBlock(p,0,uip_len);
|
||||
Enc28J60Network::resizeBlock(u->packets_out[0],0,uip_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
uip_len = UIPEthernet.network.blockSize(p);
|
||||
uip_len = Enc28J60Network::blockSize(u->packets_out[0]);
|
||||
if (uip_len > 0)
|
||||
{
|
||||
UIPEthernet.uip_hdrlen = ((uint8_t*)uip_appdata)-uip_buf;
|
||||
UIPEthernet.uip_packet = UIPEthernet.network.allocBlock(UIPEthernet.uip_hdrlen+uip_len);
|
||||
if (UIPEthernet.uip_packet != NOBLOCK)
|
||||
UIPEthernetClass::uip_hdrlen = ((uint8_t*)uip_appdata)-uip_buf;
|
||||
UIPEthernetClass::uip_packet = Enc28J60Network::allocBlock(UIPEthernetClass::uip_hdrlen+uip_len);
|
||||
if (UIPEthernetClass::uip_packet != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.copyPacket(UIPEthernet.uip_packet,UIPEthernet.uip_hdrlen,p,0,uip_len);
|
||||
UIPEthernet.packetstate |= UIPETHERNET_SENDPACKET;
|
||||
Enc28J60Network::copyPacket(UIPEthernetClass::uip_packet,UIPEthernetClass::uip_hdrlen,u->packets_out[0],0,uip_len);
|
||||
UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET;
|
||||
uip_send(uip_appdata,uip_len);
|
||||
}
|
||||
return;
|
||||
@@ -441,23 +448,30 @@ finish_newdata:
|
||||
if (u->state & UIP_CLIENT_CLOSE)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.print(F("UIPClient state UIP_CLIENT_CLOSE"));
|
||||
Serial.println(F("UIPClient state UIP_CLIENT_CLOSE"));
|
||||
UIPClient::_dumpAllData();
|
||||
#endif
|
||||
if (u->packets_out[0] == NOBLOCK)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.print(F("UIPClient state UIP_CLIENT_CLOSE -> free userdata"));
|
||||
#endif
|
||||
u->state = 0;
|
||||
uip_conn->appstate = NULL;
|
||||
uip_close();
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("no blocks out -> free userdata"));
|
||||
UIPClient::_dumpAllData();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
uip_stop();
|
||||
{
|
||||
uip_stop();
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("blocks outstanding transfer -> uip_stop()"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
nodata:
|
||||
UIPEthernet.uip_packet = NOBLOCK;
|
||||
UIPEthernetClass::uip_packet = NOBLOCK;
|
||||
uip_len=0;
|
||||
}
|
||||
|
||||
@@ -477,13 +491,15 @@ UIPClient::_allocateData()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memhandle*
|
||||
uint8_t
|
||||
UIPClient::_currentBlock(memhandle* block)
|
||||
{
|
||||
for(memhandle* end = block+UIP_SOCKET_NUMPACKETS-1; block < end; block++)
|
||||
if(*(block+1) == NOBLOCK)
|
||||
break;
|
||||
return block;
|
||||
for (uint8_t i = 1; i < UIP_SOCKET_NUMPACKETS; i++)
|
||||
{
|
||||
if (block[i] == NOBLOCK)
|
||||
return i-1;
|
||||
}
|
||||
return UIP_SOCKET_NUMPACKETS-1;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -493,19 +509,20 @@ UIPClient::_eatBlock(memhandle* block)
|
||||
memhandle* start = block;
|
||||
Serial.print(F("eatblock("));
|
||||
Serial.print(*block);
|
||||
Serial.print("): ");
|
||||
Serial.print(F("): "));
|
||||
for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++)
|
||||
{
|
||||
Serial.print(start[i]);
|
||||
Serial.print(" ");
|
||||
Serial.print(F(" "));
|
||||
}
|
||||
Serial.print("-> ");
|
||||
Serial.print(F("-> "));
|
||||
#endif
|
||||
memhandle* end = block+(UIP_SOCKET_NUMPACKETS-1);
|
||||
UIPEthernet.network.freeBlock(*block);
|
||||
while(block < end)
|
||||
*block = *((block++)+1);
|
||||
*end = NOBLOCK;
|
||||
Enc28J60Network::freeBlock(block[0]);
|
||||
for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS-1; i++)
|
||||
{
|
||||
block[i] = block[i+1];
|
||||
}
|
||||
block[UIP_SOCKET_NUMPACKETS-1] = NOBLOCK;
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++)
|
||||
{
|
||||
@@ -519,15 +536,46 @@ UIPClient::_eatBlock(memhandle* block)
|
||||
void
|
||||
UIPClient::_flushBlocks(memhandle* block)
|
||||
{
|
||||
for(memhandle* end = block+UIP_SOCKET_NUMPACKETS; block < end; block++)
|
||||
for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++)
|
||||
{
|
||||
if(*block != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(*block);
|
||||
*block = NOBLOCK;
|
||||
}
|
||||
else
|
||||
break;
|
||||
Enc28J60Network::freeBlock(block[i]);
|
||||
block[i] = NOBLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
void
|
||||
UIPClient::_dumpAllData() {
|
||||
for (uint8_t i=0; i < UIP_CONNS; i++)
|
||||
{
|
||||
Serial.print(F("UIPClient::all_data["));
|
||||
Serial.print(i);
|
||||
Serial.print(F("], state:"));
|
||||
Serial.println(all_data[i].state, BIN);
|
||||
Serial.print(F("packets_in: "));
|
||||
for (uint8_t j=0; j < UIP_SOCKET_NUMPACKETS; j++)
|
||||
{
|
||||
Serial.print(all_data[i].packets_in[j]);
|
||||
Serial.print(F(" "));
|
||||
}
|
||||
Serial.println();
|
||||
if (all_data[i].state & UIP_CLIENT_REMOTECLOSED)
|
||||
{
|
||||
Serial.print(F("state remote closed, local port: "));
|
||||
Serial.println(htons(((uip_userdata_closed_t *)(&all_data[i]))->lport));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("packets_out: "));
|
||||
for (uint8_t j=0; j < UIP_SOCKET_NUMPACKETS; j++)
|
||||
{
|
||||
Serial.print(all_data[i].packets_out[j]);
|
||||
Serial.print(F(" "));
|
||||
}
|
||||
Serial.println();
|
||||
Serial.print(F("out_pos: "));
|
||||
Serial.println(all_data[i].out_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define UIPCLIENT_H
|
||||
|
||||
#include "ethernet_comp.h"
|
||||
#include "Print.h"
|
||||
#import "Client.h"
|
||||
#import "utility/mempool.h"
|
||||
|
||||
@@ -36,9 +37,9 @@ extern "C" {
|
||||
|
||||
#define UIP_CLIENT_CONNECTED 0x10
|
||||
#define UIP_CLIENT_CLOSE 0x20
|
||||
#define UIP_CLIENT_CLOSED 0x40
|
||||
#define UIP_CLIENT_REMOTECLOSED 0x40
|
||||
#define UIP_CLIENT_RESTART 0x80
|
||||
#define UIP_CLIENT_STATEFLAGS (UIP_CLIENT_CONNECTED | UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED | UIP_CLIENT_RESTART)
|
||||
#define UIP_CLIENT_STATEFLAGS (UIP_CLIENT_CONNECTED | UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED | UIP_CLIENT_RESTART)
|
||||
#define UIP_CLIENT_SOCKETS ~UIP_CLIENT_STATEFLAGS
|
||||
|
||||
typedef uint8_t uip_socket_ptr;
|
||||
@@ -76,6 +77,8 @@ public:
|
||||
int peek();
|
||||
void flush();
|
||||
|
||||
using Print::write;
|
||||
|
||||
private:
|
||||
UIPClient(struct uip_conn *_conn);
|
||||
UIPClient(uip_userdata_t* conn_data);
|
||||
@@ -84,21 +87,23 @@ private:
|
||||
|
||||
static uip_userdata_t all_data[UIP_CONNS];
|
||||
static uip_userdata_t* _allocateData();
|
||||
static uip_userdata_t* _getData(struct uip_conn * conn);
|
||||
|
||||
|
||||
static size_t _write(uip_userdata_t *,const uint8_t *buf, size_t size);
|
||||
static int _available(uip_userdata_t *);
|
||||
|
||||
static memhandle * _currentBlock(memhandle* blocks);
|
||||
static uint8_t _currentBlock(memhandle* blocks);
|
||||
static void _eatBlock(memhandle* blocks);
|
||||
static void _flushBlocks(memhandle* blocks);
|
||||
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
static void _dumpAllData();
|
||||
#endif
|
||||
|
||||
friend class UIPEthernetClass;
|
||||
friend class UIPServer;
|
||||
|
||||
friend void uipclient_appcall(void);
|
||||
|
||||
static void uip_callback();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "HardwareSerial.h"
|
||||
#endif
|
||||
|
||||
#include "UIPUdp.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "utility/uip-conf.h"
|
||||
@@ -35,18 +37,24 @@ extern "C"
|
||||
|
||||
#define ETH_HDR ((struct uip_eth_hdr *)&uip_buf[0])
|
||||
|
||||
memhandle UIPEthernetClass::in_packet(NOBLOCK);
|
||||
memhandle UIPEthernetClass::uip_packet(NOBLOCK);
|
||||
uint8_t UIPEthernetClass::uip_hdrlen(0);
|
||||
uint8_t UIPEthernetClass::packetstate(0);
|
||||
|
||||
IPAddress UIPEthernetClass::_dnsServerAddress;
|
||||
DhcpClass* UIPEthernetClass::_dhcp(NULL);
|
||||
|
||||
struct uip_timer UIPEthernetClass::periodic_timer;
|
||||
|
||||
// Because uIP isn't encapsulated within a class we have to use global
|
||||
// variables, so we can only have one TCP/IP stack per program.
|
||||
|
||||
UIPEthernetClass::UIPEthernetClass() :
|
||||
in_packet(NOBLOCK),
|
||||
uip_packet(NOBLOCK),
|
||||
uip_hdrlen(0),
|
||||
packetstate(0),
|
||||
_dhcp(NULL)
|
||||
UIPEthernetClass::UIPEthernetClass()
|
||||
{
|
||||
}
|
||||
|
||||
#if UIP_UDP
|
||||
int
|
||||
UIPEthernetClass::begin(const uint8_t* mac)
|
||||
{
|
||||
@@ -66,6 +74,7 @@ UIPEthernetClass::begin(const uint8_t* mac)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip)
|
||||
@@ -100,6 +109,7 @@ UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddre
|
||||
int UIPEthernetClass::maintain(){
|
||||
tick();
|
||||
int rc = DHCP_CHECK_NONE;
|
||||
#if UIP_UDP
|
||||
if(_dhcp != NULL){
|
||||
//we have a pointer to dhcp, use it
|
||||
rc = _dhcp->checkLease();
|
||||
@@ -118,6 +128,7 @@ int UIPEthernetClass::maintain(){
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
IPAddress UIPEthernetClass::localIP()
|
||||
@@ -154,7 +165,7 @@ UIPEthernetClass::tick()
|
||||
{
|
||||
if (in_packet == NOBLOCK)
|
||||
{
|
||||
in_packet = network.receivePacket();
|
||||
in_packet = Enc28J60Network::receivePacket();
|
||||
#ifdef UIPETHERNET_DEBUG
|
||||
if (in_packet != NOBLOCK)
|
||||
{
|
||||
@@ -166,10 +177,10 @@ UIPEthernetClass::tick()
|
||||
if (in_packet != NOBLOCK)
|
||||
{
|
||||
packetstate = UIPETHERNET_FREEPACKET;
|
||||
uip_len = network.blockSize(in_packet);
|
||||
uip_len = Enc28J60Network::blockSize(in_packet);
|
||||
if (uip_len > 0)
|
||||
{
|
||||
network.readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE);
|
||||
Enc28J60Network::readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE);
|
||||
if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP))
|
||||
{
|
||||
uip_packet = in_packet;
|
||||
@@ -204,7 +215,7 @@ UIPEthernetClass::tick()
|
||||
Serial.print(F("freeing packet: "));
|
||||
Serial.println(in_packet);
|
||||
#endif
|
||||
network.freePacket();
|
||||
Enc28J60Network::freePacket();
|
||||
in_packet = NOBLOCK;
|
||||
}
|
||||
}
|
||||
@@ -216,7 +227,7 @@ UIPEthernetClass::tick()
|
||||
{
|
||||
uip_periodic(i);
|
||||
// If the above function invocation resulted in data that
|
||||
// should be sent out on the network, the global variable
|
||||
// should be sent out on the Enc28J60Network, the global variable
|
||||
// uip_len is set to a value > 0.
|
||||
if (uip_len > 0)
|
||||
{
|
||||
@@ -230,11 +241,11 @@ UIPEthernetClass::tick()
|
||||
{
|
||||
uip_udp_periodic(i);
|
||||
// If the above function invocation resulted in data that
|
||||
// should be sent out on the network, the global variable
|
||||
// should be sent out on the Enc28J60Network, the global variable
|
||||
// uip_len is set to a value > 0. */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
network_send();
|
||||
UIPUDP::_send((uip_udp_userdata_t *)(uip_udp_conns[i].appstate));
|
||||
}
|
||||
}
|
||||
#endif /* UIP_UDP */
|
||||
@@ -246,41 +257,42 @@ boolean UIPEthernetClass::network_send()
|
||||
if (packetstate & UIPETHERNET_SENDPACKET)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG
|
||||
Serial.print(F("network_send uip_packet: "));
|
||||
Serial.print(F("Enc28J60Network_send uip_packet: "));
|
||||
Serial.print(uip_packet);
|
||||
Serial.print(F(", hdrlen: "));
|
||||
Serial.println(uip_hdrlen);
|
||||
#endif
|
||||
network.writePacket(uip_packet,0,uip_buf,uip_hdrlen);
|
||||
Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_hdrlen);
|
||||
goto sendandfree;
|
||||
}
|
||||
uip_packet = network.allocBlock(uip_len);
|
||||
uip_packet = Enc28J60Network::allocBlock(uip_len);
|
||||
if (uip_packet != NOBLOCK)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG
|
||||
Serial.print(F("network_send uip_buf (uip_len): "));
|
||||
Serial.print(F("Enc28J60Network_send uip_buf (uip_len): "));
|
||||
Serial.print(uip_len);
|
||||
Serial.print(F(", packet: "));
|
||||
Serial.println(uip_packet);
|
||||
#endif
|
||||
network.writePacket(uip_packet,0,uip_buf,uip_len);
|
||||
Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_len);
|
||||
goto sendandfree;
|
||||
}
|
||||
return false;
|
||||
sendandfree:
|
||||
network.sendPacket(uip_packet);
|
||||
network.freeBlock(uip_packet);
|
||||
Enc28J60Network::sendPacket(uip_packet);
|
||||
Enc28J60Network::freeBlock(uip_packet);
|
||||
uip_packet = NOBLOCK;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIPEthernetClass::init(const uint8_t* mac) {
|
||||
uip_timer_set(&this->periodic_timer, CLOCK_SECOND / 4);
|
||||
uip_timer_set(&periodic_timer, CLOCK_SECOND / 4);
|
||||
|
||||
network.init((uint8_t*)mac);
|
||||
Enc28J60Network::init((uint8_t*)mac);
|
||||
uip_seteth_addr(mac);
|
||||
|
||||
uip_init();
|
||||
uip_arp_init();
|
||||
}
|
||||
|
||||
void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) {
|
||||
@@ -345,7 +357,11 @@ UIPEthernetClass::ipchksum(void)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint16_t
|
||||
#if UIP_UDP
|
||||
UIPEthernetClass::upper_layer_chksum(uint8_t proto)
|
||||
#else
|
||||
uip_tcpchksum(void)
|
||||
#endif
|
||||
{
|
||||
uint16_t upper_layer_len;
|
||||
uint16_t sum;
|
||||
@@ -359,27 +375,34 @@ UIPEthernetClass::upper_layer_chksum(uint8_t proto)
|
||||
/* First sum pseudoheader. */
|
||||
|
||||
/* IP protocol and length fields. This addition cannot carry. */
|
||||
#if UIP_UDP
|
||||
sum = upper_layer_len + proto;
|
||||
#else
|
||||
sum = upper_layer_len + UIP_PROTO_TCP;
|
||||
#endif
|
||||
/* Sum IP source and destination addresses. */
|
||||
sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
|
||||
sum = UIPEthernetClass::chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
|
||||
|
||||
uint8_t upper_layer_memlen;
|
||||
#if UIP_UDP
|
||||
switch(proto)
|
||||
{
|
||||
case UIP_PROTO_ICMP:
|
||||
case UIP_PROTO_ICMP6:
|
||||
upper_layer_memlen = upper_layer_len;
|
||||
break;
|
||||
case UIP_PROTO_TCP:
|
||||
upper_layer_memlen = (BUF->tcpoffset >> 4) << 2;
|
||||
break;
|
||||
#if UIP_UDP
|
||||
case UIP_PROTO_UDP:
|
||||
// case UIP_PROTO_ICMP:
|
||||
// case UIP_PROTO_ICMP6:
|
||||
// upper_layer_memlen = upper_layer_len;
|
||||
// break;
|
||||
case UIP_PROTO_UDP:
|
||||
upper_layer_memlen = UIP_UDPH_LEN;
|
||||
break;
|
||||
default:
|
||||
// case UIP_PROTO_TCP:
|
||||
#endif
|
||||
upper_layer_memlen = (BUF->tcpoffset >> 4) << 2;
|
||||
#if UIP_UDP
|
||||
break;
|
||||
}
|
||||
sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen);
|
||||
#endif
|
||||
sum = UIPEthernetClass::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen);
|
||||
#ifdef UIPETHERNET_DEBUG_CHKSUM
|
||||
Serial.print(F("chksum uip_buf["));
|
||||
Serial.print(UIP_IPH_LEN + UIP_LLH_LEN);
|
||||
@@ -390,9 +413,9 @@ UIPEthernetClass::upper_layer_chksum(uint8_t proto)
|
||||
#endif
|
||||
if (upper_layer_memlen < upper_layer_len)
|
||||
{
|
||||
sum = network.chksum(
|
||||
sum = Enc28J60Network::chksum(
|
||||
sum,
|
||||
uip_packet,
|
||||
UIPEthernetClass::uip_packet,
|
||||
UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen,
|
||||
upper_layer_len - upper_layer_memlen
|
||||
);
|
||||
@@ -403,7 +426,7 @@ UIPEthernetClass::upper_layer_chksum(uint8_t proto)
|
||||
Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen);
|
||||
Serial.print(F("-"));
|
||||
Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len);
|
||||
Serial.print(F"]: "));
|
||||
Serial.print(F("]: "));
|
||||
Serial.println(htons(sum),HEX);
|
||||
#endif
|
||||
}
|
||||
@@ -416,6 +439,7 @@ uip_ipchksum(void)
|
||||
return UIPEthernet.ipchksum();
|
||||
}
|
||||
|
||||
#if UIP_UDP
|
||||
uint16_t
|
||||
uip_tcpchksum(void)
|
||||
{
|
||||
@@ -423,7 +447,6 @@ uip_tcpchksum(void)
|
||||
return sum;
|
||||
}
|
||||
|
||||
#if UIP_UDP
|
||||
uint16_t
|
||||
uip_udpchksum(void)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
#ifndef UIPETHERNET_H
|
||||
#define UIPETHERNET_H
|
||||
|
||||
//#define UIPETHERNET_DEBUG
|
||||
//#define UIPETHERNET_DEBUG_CHKSUM
|
||||
//#define UIPETHERNET_DEBUG_UDP
|
||||
//#define UIPETHERNET_DEBUG_CLIENT
|
||||
|
||||
#include "ethernet_comp.h"
|
||||
#include <Arduino.h>
|
||||
#include "Dhcp.h"
|
||||
@@ -35,11 +40,6 @@ extern "C"
|
||||
#include "utility/uip.h"
|
||||
}
|
||||
|
||||
//#define UIPETHERNET_DEBUG
|
||||
//#define UIPETHERNET_DEBUG_CHKSUM
|
||||
//#define UIPETHERNET_DEBUG_UDP
|
||||
//#define UIPETHERNET_DEBUG_CLIENT
|
||||
|
||||
#define UIPETHERNET_FREEPACKET 1
|
||||
#define UIPETHERNET_SENDPACKET 2
|
||||
#define UIPETHERNET_BUFFERREAD 4
|
||||
@@ -82,24 +82,22 @@ public:
|
||||
IPAddress dnsServerIP();
|
||||
|
||||
private:
|
||||
IPAddress _dnsServerAddress;
|
||||
DhcpClass* _dhcp;
|
||||
static memhandle in_packet;
|
||||
static memhandle uip_packet;
|
||||
static uint8_t uip_hdrlen;
|
||||
static uint8_t packetstate;
|
||||
|
||||
static IPAddress _dnsServerAddress;
|
||||
static DhcpClass* _dhcp;
|
||||
|
||||
struct uip_timer periodic_timer;
|
||||
static struct uip_timer periodic_timer;
|
||||
|
||||
memhandle in_packet;
|
||||
memhandle uip_packet;
|
||||
uint8_t uip_hdrlen;
|
||||
uint8_t packetstate;
|
||||
static void init(const uint8_t* mac);
|
||||
static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);
|
||||
|
||||
Enc28J60Network network;
|
||||
static void tick();
|
||||
|
||||
void init(const uint8_t* mac);
|
||||
void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);
|
||||
|
||||
void tick();
|
||||
|
||||
boolean network_send();
|
||||
static boolean network_send();
|
||||
|
||||
friend class UIPServer;
|
||||
|
||||
@@ -109,12 +107,16 @@ private:
|
||||
|
||||
static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len);
|
||||
static uint16_t ipchksum(void);
|
||||
uint16_t upper_layer_chksum(uint8_t proto);
|
||||
|
||||
#if UIP_UDP
|
||||
static uint16_t upper_layer_chksum(uint8_t proto);
|
||||
#endif
|
||||
friend uint16_t uip_ipchksum(void);
|
||||
friend uint16_t uip_tcpchksum(void);
|
||||
friend uint16_t uip_udpchksum(void);
|
||||
|
||||
friend void uipclient_appcall(void);
|
||||
friend void uipudp_appcall(void);
|
||||
|
||||
#if UIP_CONF_IPV6
|
||||
uint16_t uip_icmp6chksum(void);
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
@@ -28,12 +28,12 @@ UIPServer::UIPServer(uint16_t port) : _port(htons(port))
|
||||
|
||||
UIPClient UIPServer::available()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
UIPEthernetClass::tick();
|
||||
for ( uip_userdata_t* data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++ )
|
||||
{
|
||||
if (data->packets_in[0] != NOBLOCK
|
||||
&& (((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport ==_port)
|
||||
|| ((data->state & UIP_CLIENT_CLOSED) && ((uip_userdata_closed_t *)data)->lport == _port)))
|
||||
|| ((data->state & UIP_CLIENT_REMOTECLOSED) && ((uip_userdata_closed_t *)data)->lport == _port)))
|
||||
return UIPClient(data);
|
||||
}
|
||||
return UIPClient();
|
||||
@@ -42,7 +42,7 @@ UIPClient UIPServer::available()
|
||||
void UIPServer::begin()
|
||||
{
|
||||
uip_listen(_port);
|
||||
UIPEthernet.tick();
|
||||
UIPEthernetClass::tick();
|
||||
}
|
||||
|
||||
size_t UIPServer::write(uint8_t c)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#import "Server.h"
|
||||
#import "UIPClient.h"
|
||||
|
||||
class UIPServer : Server {
|
||||
class UIPServer : public Server {
|
||||
|
||||
public:
|
||||
UIPServer(uint16_t);
|
||||
|
||||
@@ -65,28 +65,13 @@ UIPUDP::stop()
|
||||
{
|
||||
if (_uip_udp_conn)
|
||||
{
|
||||
flush();
|
||||
uip_udp_remove(_uip_udp_conn);
|
||||
_uip_udp_conn->appstate = NULL;
|
||||
_uip_udp_conn=NULL;
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(appdata.packet_in);
|
||||
appdata.packet_in = NOBLOCK;
|
||||
}
|
||||
uint8_t i = 0;
|
||||
memhandle* packet = &appdata.packets_in[0];
|
||||
while (*packet != NOBLOCK && i < UIP_UDP_NUMPACKETS)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(*packet);
|
||||
*packet++ = NOBLOCK;
|
||||
i++;
|
||||
}
|
||||
if (appdata.packet_out != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(appdata.packet_out);
|
||||
appdata.packet_out = NOBLOCK;
|
||||
}
|
||||
Enc28J60Network::freeBlock(appdata.packet_in);
|
||||
Enc28J60Network::freeBlock(appdata.packet_next);
|
||||
Enc28J60Network::freeBlock(appdata.packet_out);
|
||||
memset(&appdata,0,sizeof(appdata));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +82,7 @@ UIPUDP::stop()
|
||||
int
|
||||
UIPUDP::beginPacket(IPAddress ip, uint16_t port)
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
UIPEthernetClass::tick();
|
||||
if (ip && port)
|
||||
{
|
||||
uip_ipaddr_t ripaddr;
|
||||
@@ -139,7 +124,7 @@ UIPUDP::beginPacket(IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (appdata.packet_out == NOBLOCK)
|
||||
{
|
||||
appdata.packet_out = UIPEthernet.network.allocBlock(UIP_UDP_MAXPACKETSIZE);
|
||||
appdata.packet_out = Enc28J60Network::allocBlock(UIP_UDP_MAXPACKETSIZE);
|
||||
appdata.out_pos = UIP_UDP_PHYH_LEN;
|
||||
if (appdata.packet_out != NOBLOCK)
|
||||
return 1;
|
||||
@@ -183,11 +168,11 @@ UIPUDP::endPacket()
|
||||
if (_uip_udp_conn && appdata.packet_out != NOBLOCK)
|
||||
{
|
||||
appdata.send = true;
|
||||
UIPEthernet.network.resizeBlock(appdata.packet_out,0,appdata.out_pos);
|
||||
Enc28J60Network::resizeBlock(appdata.packet_out,0,appdata.out_pos);
|
||||
uip_udp_periodic_conn(_uip_udp_conn);
|
||||
if (uip_len > 0)
|
||||
{
|
||||
UIPEthernet.network_send();
|
||||
_send(&appdata);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -207,7 +192,7 @@ UIPUDP::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
if (appdata.packet_out != NOBLOCK)
|
||||
{
|
||||
size_t ret = UIPEthernet.network.writePacket(appdata.packet_out,appdata.out_pos,(uint8_t*)buffer,size);
|
||||
size_t ret = Enc28J60Network::writePacket(appdata.packet_out,appdata.out_pos,(uint8_t*)buffer,size);
|
||||
appdata.out_pos += ret;
|
||||
return ret;
|
||||
}
|
||||
@@ -219,61 +204,43 @@ UIPUDP::write(const uint8_t *buffer, size_t size)
|
||||
int
|
||||
UIPUDP::parsePacket()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
UIPEthernetClass::tick();
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp parsePacket freeing previous packet: "));
|
||||
Serial.println(appdata.packet_in);
|
||||
#endif;
|
||||
UIPEthernet.network.freeBlock(appdata.packet_in);
|
||||
}
|
||||
memhandle *packet = &appdata.packets_in[0];
|
||||
appdata.packet_in = *packet;
|
||||
#endif
|
||||
Enc28J60Network::freeBlock(appdata.packet_in);
|
||||
|
||||
appdata.packet_in = appdata.packet_next;
|
||||
appdata.packet_next = NOBLOCK;
|
||||
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp parsePacket received packet: "));
|
||||
Serial.print(appdata.packet_in);
|
||||
}
|
||||
#endif
|
||||
if (UIP_UDP_NUMPACKETS > 1)
|
||||
{
|
||||
uint8_t i = 1;
|
||||
memhandle* p = packet+1;
|
||||
freeloop:
|
||||
*packet = *p;
|
||||
if (*packet == NOBLOCK)
|
||||
goto freeready;
|
||||
packet++;
|
||||
if (i < UIP_UDP_NUMPACKETS-1)
|
||||
{
|
||||
i++;
|
||||
p++;
|
||||
goto freeloop;
|
||||
}
|
||||
}
|
||||
*packet = NOBLOCK;
|
||||
freeready:
|
||||
int size = UIPEthernet.network.blockSize(appdata.packet_in);
|
||||
int size = Enc28J60Network::blockSize(appdata.packet_in);
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
Serial.print(F(", size: "));
|
||||
Serial.println(size);
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
|
||||
// Number of bytes remaining in the current packet
|
||||
int
|
||||
UIPUDP::available()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
return UIPEthernet.network.blockSize(appdata.packet_in);
|
||||
}
|
||||
return 0;
|
||||
UIPEthernetClass::tick();
|
||||
return Enc28J60Network::blockSize(appdata.packet_in);
|
||||
}
|
||||
|
||||
// Read a single byte from the current packet
|
||||
@@ -293,11 +260,17 @@ UIPUDP::read()
|
||||
int
|
||||
UIPUDP::read(unsigned char* buffer, size_t len)
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
UIPEthernetClass::tick();
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
int read = UIPEthernet.network.readPacket(appdata.packet_in,0,buffer,len);
|
||||
UIPEthernet.network.resizeBlock(appdata.packet_in,read);
|
||||
memaddress read = Enc28J60Network::readPacket(appdata.packet_in,0,buffer,len);
|
||||
if (read == Enc28J60Network::blockSize(appdata.packet_in))
|
||||
{
|
||||
Enc28J60Network::freeBlock(appdata.packet_in);
|
||||
appdata.packet_in = NOBLOCK;
|
||||
}
|
||||
else
|
||||
Enc28J60Network::resizeBlock(appdata.packet_in,read);
|
||||
return read;
|
||||
}
|
||||
return 0;
|
||||
@@ -307,11 +280,11 @@ UIPUDP::read(unsigned char* buffer, size_t len)
|
||||
int
|
||||
UIPUDP::peek()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
UIPEthernetClass::tick();
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
unsigned char c;
|
||||
if (UIPEthernet.network.readPacket(appdata.packet_in,0,&c,1) == 1)
|
||||
if (Enc28J60Network::readPacket(appdata.packet_in,0,&c,1) == 1)
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
@@ -321,12 +294,9 @@ UIPUDP::peek()
|
||||
void
|
||||
UIPUDP::flush()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(appdata.packet_in);
|
||||
appdata.packet_in = NOBLOCK;
|
||||
}
|
||||
UIPEthernetClass::tick();
|
||||
Enc28J60Network::freeBlock(appdata.packet_in);
|
||||
appdata.packet_in = NOBLOCK;
|
||||
}
|
||||
|
||||
// Return the IP address of the host who sent the current incoming packet
|
||||
@@ -347,44 +317,28 @@ UIPUDP::remotePort()
|
||||
|
||||
void
|
||||
uipudp_appcall(void) {
|
||||
UIPUDP::uip_callback();
|
||||
}
|
||||
|
||||
void
|
||||
UIPUDP::uip_callback() {
|
||||
if (appdata_t *data = (appdata_t *)(uip_udp_conn->appstate))
|
||||
if (uip_udp_userdata_t *data = (uip_udp_userdata_t *)(uip_udp_conn->appstate))
|
||||
{
|
||||
if (uip_newdata())
|
||||
{
|
||||
uip_udp_conn->rport = UDPBUF->srcport;
|
||||
uip_ipaddr_copy(uip_udp_conn->ripaddr,UDPBUF->srcipaddr);
|
||||
memhandle *packet = &data->packets_in[0];
|
||||
uint8_t i = 0;
|
||||
do
|
||||
if (data->packet_next == NOBLOCK)
|
||||
{
|
||||
if (*packet == NOBLOCK)
|
||||
{
|
||||
*packet = UIPEthernet.network.allocBlock(ntohs(UDPBUF->udplen)-UIP_UDPH_LEN);
|
||||
uip_udp_conn->rport = UDPBUF->srcport;
|
||||
uip_ipaddr_copy(uip_udp_conn->ripaddr,UDPBUF->srcipaddr);
|
||||
data->packet_next = Enc28J60Network::allocBlock(ntohs(UDPBUF->udplen)-UIP_UDPH_LEN);
|
||||
//if we are unable to allocate memory the packet is dropped. udp doesn't guarantee packet delivery
|
||||
if (*packet != NOBLOCK)
|
||||
{
|
||||
//discard Linklevel and IP and udp-header and any trailing bytes:
|
||||
UIPEthernet.network.copyPacket(*packet,0,UIPEthernet.in_packet,UIP_UDP_PHYH_LEN,UIPEthernet.network.blockSize(*packet));
|
||||
if (data->packet_next != NOBLOCK)
|
||||
{
|
||||
//discard Linklevel and IP and udp-header and any trailing bytes:
|
||||
Enc28J60Network::copyPacket(data->packet_next,0,UIPEthernetClass::in_packet,UIP_UDP_PHYH_LEN,Enc28J60Network::blockSize(data->packet_next));
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp, uip_newdata received packet: "));
|
||||
Serial.print(*packet);
|
||||
Serial.print(F(", slot: "));
|
||||
Serial.print(i);
|
||||
Serial.print(F(", size: "));
|
||||
Serial.println(UIPEthernet.network.blockSize(*packet));
|
||||
Serial.print(F("udp, uip_newdata received packet: "));
|
||||
Serial.print(data->packet_next);
|
||||
Serial.print(F(", size: "));
|
||||
Serial.println(Enc28J60Network::blockSize(data->packet_next));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
packet++;
|
||||
i++;
|
||||
}
|
||||
while (i < UIP_UDP_NUMPACKETS);
|
||||
}
|
||||
if (uip_poll() && data->send)
|
||||
{
|
||||
@@ -393,32 +347,37 @@ UIPUDP::uip_callback() {
|
||||
Serial.print(F("udp, uip_poll preparing packet to send: "));
|
||||
Serial.print(data->packet_out);
|
||||
Serial.print(F(", size: "));
|
||||
Serial.println(UIPEthernet.network.blockSize(data->packet_out));
|
||||
Serial.println(Enc28J60Network::blockSize(data->packet_out));
|
||||
#endif
|
||||
UIPEthernet.uip_packet = data->packet_out;
|
||||
data->packet_out = NOBLOCK;
|
||||
UIPEthernet.uip_hdrlen = UIP_UDP_PHYH_LEN;
|
||||
UIPEthernet.packetstate |= UIPETHERNET_SENDPACKET;
|
||||
UIPEthernetClass::uip_packet = data->packet_out;
|
||||
UIPEthernetClass::uip_hdrlen = UIP_UDP_PHYH_LEN;
|
||||
uip_udp_send(data->out_pos - (UIP_UDP_PHYH_LEN));
|
||||
uip_process(UIP_UDP_SEND_CONN); //generate udp + ip headers
|
||||
uip_arp_out(); //add arp
|
||||
if (uip_len == UIP_ARPHDRSIZE)
|
||||
{
|
||||
UIPEthernet.packetstate &= ~UIPETHERNET_SENDPACKET;
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.println(F("udp, uip_poll results in ARP-packet"));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
//arp found ethaddr for ip (otherwise packet is replaced by arp-request)
|
||||
{
|
||||
data->send = false;
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp, uip_packet to send: "));
|
||||
Serial.println(UIPEthernet.uip_packet);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIPUDP::_send(uip_udp_userdata_t *data) {
|
||||
uip_arp_out(); //add arp
|
||||
if (uip_len == UIP_ARPHDRSIZE)
|
||||
{
|
||||
UIPEthernetClass::uip_packet = NOBLOCK;
|
||||
UIPEthernetClass::packetstate &= ~UIPETHERNET_SENDPACKET;
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.println(F("udp, uip_poll results in ARP-packet"));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
//arp found ethaddr for ip (otherwise packet is replaced by arp-request)
|
||||
{
|
||||
data->send = false;
|
||||
data->packet_out = NOBLOCK;
|
||||
UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET;
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp, uip_packet to send: "));
|
||||
Serial.println(UIPEthernetClass::uip_packet);
|
||||
#endif
|
||||
}
|
||||
UIPEthernetClass::network_send();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -25,15 +25,20 @@
|
||||
#include <Udp.h>
|
||||
#include "utility/mempool.h"
|
||||
extern "C" {
|
||||
#include "utility/uip.h";
|
||||
#include "utility/uip.h"
|
||||
}
|
||||
|
||||
#define UIP_UDP_MAXDATALEN 1500
|
||||
#define UIP_UDP_PHYH_LEN UIP_LLH_LEN+UIP_IPUDPH_LEN
|
||||
#define UIP_UDP_MAXPACKETSIZE UIP_UDP_MAXDATALEN+UIP_UDP_PHYH_LEN
|
||||
#ifndef UIP_UDP_NUMPACKETS
|
||||
#define UIP_UDP_NUMPACKETS 5
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
memaddress out_pos;
|
||||
memhandle packet_next;
|
||||
memhandle packet_in;
|
||||
memhandle packet_out;
|
||||
boolean send;
|
||||
} uip_udp_userdata_t;
|
||||
|
||||
class UIPUDP : public UDP
|
||||
{
|
||||
@@ -41,14 +46,7 @@ class UIPUDP : public UDP
|
||||
private:
|
||||
struct uip_udp_conn *_uip_udp_conn;
|
||||
|
||||
struct appdata_t
|
||||
{
|
||||
memaddress out_pos;
|
||||
memhandle packets_in[UIP_UDP_NUMPACKETS];
|
||||
memhandle packet_in;
|
||||
memhandle packet_out;
|
||||
boolean send;
|
||||
} appdata;
|
||||
uip_udp_userdata_t appdata;
|
||||
|
||||
public:
|
||||
UIPUDP(); // Constructor
|
||||
@@ -120,7 +118,9 @@ private:
|
||||
|
||||
friend void uipudp_appcall(void);
|
||||
|
||||
static void uip_callback();
|
||||
friend class UIPEthernetClass;
|
||||
static void _send(uip_udp_userdata_t *data);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
#define Ethernet UIPEthernet
|
||||
#define EthernetClient UIPClient
|
||||
#define EthernetServer UIPServer
|
||||
//#define EthernetUDP UIPUDP
|
||||
#define EthernetUDP UIPUDP
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,478 +0,0 @@
|
||||
// DHCP Library v0.3 - April 25, 2009
|
||||
// Author: Jordan Terrell - blog.jordanterrell.com
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "Dhcp.h"
|
||||
#include "Arduino.h"
|
||||
#include "utility/util.h"
|
||||
|
||||
int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
|
||||
{
|
||||
_dhcpLeaseTime=0;
|
||||
_dhcpT1=0;
|
||||
_dhcpT2=0;
|
||||
_lastCheck=0;
|
||||
_timeout = timeout;
|
||||
_responseTimeout = responseTimeout;
|
||||
|
||||
// zero out _dhcpMacAddr
|
||||
memset(_dhcpMacAddr, 0, 6);
|
||||
reset_DHCP_lease();
|
||||
|
||||
memcpy((void*)_dhcpMacAddr, (void*)mac, 6);
|
||||
_dhcp_state = STATE_DHCP_START;
|
||||
return request_DHCP_lease();
|
||||
}
|
||||
|
||||
void DhcpClass::reset_DHCP_lease(){
|
||||
// zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
|
||||
memset(_dhcpLocalIp, 0, 20);
|
||||
}
|
||||
|
||||
//return:0 on error, 1 if request is sent and response is received
|
||||
int DhcpClass::request_DHCP_lease(){
|
||||
|
||||
uint8_t messageType = 0;
|
||||
|
||||
|
||||
|
||||
// Pick an initial transaction ID
|
||||
_dhcpTransactionId = random(1UL, 2000UL);
|
||||
_dhcpInitialTransactionId = _dhcpTransactionId;
|
||||
|
||||
_dhcpUdpSocket.stop();
|
||||
if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0)
|
||||
{
|
||||
// Couldn't get a socket
|
||||
return 0;
|
||||
}
|
||||
|
||||
presend_DHCP();
|
||||
|
||||
int result = 0;
|
||||
|
||||
unsigned long startTime = millis();
|
||||
|
||||
while(_dhcp_state != STATE_DHCP_LEASED)
|
||||
{
|
||||
if(_dhcp_state == STATE_DHCP_START)
|
||||
{
|
||||
_dhcpTransactionId++;
|
||||
|
||||
send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000));
|
||||
_dhcp_state = STATE_DHCP_DISCOVER;
|
||||
}
|
||||
else if(_dhcp_state == STATE_DHCP_REREQUEST){
|
||||
_dhcpTransactionId++;
|
||||
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000));
|
||||
_dhcp_state = STATE_DHCP_REQUEST;
|
||||
}
|
||||
else if(_dhcp_state == STATE_DHCP_DISCOVER)
|
||||
{
|
||||
uint32_t respId;
|
||||
messageType = parseDHCPResponse(_responseTimeout, respId);
|
||||
if(messageType == DHCP_OFFER)
|
||||
{
|
||||
// We'll use the transaction ID that the offer came with,
|
||||
// rather than the one we were up to
|
||||
_dhcpTransactionId = respId;
|
||||
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000));
|
||||
_dhcp_state = STATE_DHCP_REQUEST;
|
||||
}
|
||||
}
|
||||
else if(_dhcp_state == STATE_DHCP_REQUEST)
|
||||
{
|
||||
uint32_t respId;
|
||||
messageType = parseDHCPResponse(_responseTimeout, respId);
|
||||
if(messageType == DHCP_ACK)
|
||||
{
|
||||
_dhcp_state = STATE_DHCP_LEASED;
|
||||
result = 1;
|
||||
//use default lease time if we didn't get it
|
||||
if(_dhcpLeaseTime == 0){
|
||||
_dhcpLeaseTime = DEFAULT_LEASE;
|
||||
}
|
||||
//calculate T1 & T2 if we didn't get it
|
||||
if(_dhcpT1 == 0){
|
||||
//T1 should be 50% of _dhcpLeaseTime
|
||||
_dhcpT1 = _dhcpLeaseTime >> 1;
|
||||
}
|
||||
if(_dhcpT2 == 0){
|
||||
//T2 should be 87.5% (7/8ths) of _dhcpLeaseTime
|
||||
_dhcpT2 = _dhcpT1 << 1;
|
||||
}
|
||||
_renewInSec = _dhcpT1;
|
||||
_rebindInSec = _dhcpT2;
|
||||
}
|
||||
else if(messageType == DHCP_NAK)
|
||||
_dhcp_state = STATE_DHCP_START;
|
||||
}
|
||||
|
||||
if(messageType == 255)
|
||||
{
|
||||
messageType = 0;
|
||||
_dhcp_state = STATE_DHCP_START;
|
||||
}
|
||||
|
||||
if(result != 1 && ((millis() - startTime) > _timeout))
|
||||
break;
|
||||
}
|
||||
|
||||
// We're done with the socket now
|
||||
_dhcpUdpSocket.stop();
|
||||
_dhcpTransactionId++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DhcpClass::presend_DHCP()
|
||||
{
|
||||
}
|
||||
|
||||
void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
|
||||
{
|
||||
uint8_t buffer[32];
|
||||
memset(buffer, 0, 32);
|
||||
IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address
|
||||
|
||||
if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT))
|
||||
{
|
||||
// FIXME Need to return errors
|
||||
return;
|
||||
}
|
||||
|
||||
buffer[0] = DHCP_BOOTREQUEST; // op
|
||||
buffer[1] = DHCP_HTYPE10MB; // htype
|
||||
buffer[2] = DHCP_HLENETHERNET; // hlen
|
||||
buffer[3] = DHCP_HOPS; // hops
|
||||
|
||||
// xid
|
||||
unsigned long xid = htonl(_dhcpTransactionId);
|
||||
memcpy(buffer + 4, &(xid), 4);
|
||||
|
||||
// 8, 9 - seconds elapsed
|
||||
buffer[8] = ((secondsElapsed & 0xff00) >> 8);
|
||||
buffer[9] = (secondsElapsed & 0x00ff);
|
||||
|
||||
// flags
|
||||
unsigned short flags = htons(DHCP_FLAGSBROADCAST);
|
||||
memcpy(buffer + 10, &(flags), 2);
|
||||
|
||||
// ciaddr: already zeroed
|
||||
// yiaddr: already zeroed
|
||||
// siaddr: already zeroed
|
||||
// giaddr: already zeroed
|
||||
|
||||
//put data in W5100 transmit buffer
|
||||
_dhcpUdpSocket.write(buffer, 28);
|
||||
|
||||
memset(buffer, 0, 32); // clear local buffer
|
||||
|
||||
memcpy(buffer, _dhcpMacAddr, 6); // chaddr
|
||||
|
||||
//put data in W5100 transmit buffer
|
||||
_dhcpUdpSocket.write(buffer, 16);
|
||||
|
||||
memset(buffer, 0, 32); // clear local buffer
|
||||
|
||||
// leave zeroed out for sname && file
|
||||
// put in W5100 transmit buffer x 6 (192 bytes)
|
||||
|
||||
for(int i = 0; i < 6; i++) {
|
||||
_dhcpUdpSocket.write(buffer, 32);
|
||||
}
|
||||
|
||||
// OPT - Magic Cookie
|
||||
buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF);
|
||||
buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF);
|
||||
buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF);
|
||||
buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF);
|
||||
|
||||
// OPT - message type
|
||||
buffer[4] = dhcpMessageType;
|
||||
buffer[5] = 0x01;
|
||||
buffer[6] = messageType; //DHCP_REQUEST;
|
||||
|
||||
// OPT - client identifier
|
||||
buffer[7] = dhcpClientIdentifier;
|
||||
buffer[8] = 0x07;
|
||||
buffer[9] = 0x01;
|
||||
memcpy(buffer + 10, _dhcpMacAddr, 6);
|
||||
|
||||
// OPT - host name
|
||||
buffer[16] = hostName;
|
||||
buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address
|
||||
strcpy((char*)&(buffer[18]), HOST_NAME);
|
||||
|
||||
printByte((char*)&(buffer[24]), _dhcpMacAddr[3]);
|
||||
printByte((char*)&(buffer[26]), _dhcpMacAddr[4]);
|
||||
printByte((char*)&(buffer[28]), _dhcpMacAddr[5]);
|
||||
|
||||
//put data in W5100 transmit buffer
|
||||
_dhcpUdpSocket.write(buffer, 30);
|
||||
|
||||
if(messageType == DHCP_REQUEST)
|
||||
{
|
||||
buffer[0] = dhcpRequestedIPaddr;
|
||||
buffer[1] = 0x04;
|
||||
buffer[2] = _dhcpLocalIp[0];
|
||||
buffer[3] = _dhcpLocalIp[1];
|
||||
buffer[4] = _dhcpLocalIp[2];
|
||||
buffer[5] = _dhcpLocalIp[3];
|
||||
|
||||
buffer[6] = dhcpServerIdentifier;
|
||||
buffer[7] = 0x04;
|
||||
buffer[8] = _dhcpDhcpServerIp[0];
|
||||
buffer[9] = _dhcpDhcpServerIp[1];
|
||||
buffer[10] = _dhcpDhcpServerIp[2];
|
||||
buffer[11] = _dhcpDhcpServerIp[3];
|
||||
|
||||
//put data in W5100 transmit buffer
|
||||
_dhcpUdpSocket.write(buffer, 12);
|
||||
}
|
||||
|
||||
buffer[0] = dhcpParamRequest;
|
||||
buffer[1] = 0x06;
|
||||
buffer[2] = subnetMask;
|
||||
buffer[3] = routersOnSubnet;
|
||||
buffer[4] = dns;
|
||||
buffer[5] = domainName;
|
||||
buffer[6] = dhcpT1value;
|
||||
buffer[7] = dhcpT2value;
|
||||
buffer[8] = endOption;
|
||||
|
||||
//put data in W5100 transmit buffer
|
||||
_dhcpUdpSocket.write(buffer, 9);
|
||||
|
||||
_dhcpUdpSocket.endPacket();
|
||||
}
|
||||
|
||||
uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId)
|
||||
{
|
||||
uint8_t type = 0;
|
||||
uint8_t opt_len = 0;
|
||||
|
||||
unsigned long startTime = millis();
|
||||
|
||||
while(_dhcpUdpSocket.parsePacket() <= 0)
|
||||
{
|
||||
if((millis() - startTime) > responseTimeout)
|
||||
{
|
||||
return 255;
|
||||
}
|
||||
delay(50);
|
||||
}
|
||||
// start reading in the packet
|
||||
RIP_MSG_FIXED fixedMsg;
|
||||
_dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED));
|
||||
|
||||
if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT)
|
||||
{
|
||||
transactionId = ntohl(fixedMsg.xid);
|
||||
if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId))
|
||||
{
|
||||
// Need to read the rest of the packet here regardless
|
||||
_dhcpUdpSocket.flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4);
|
||||
|
||||
// Skip to the option part
|
||||
// Doing this a byte at a time so we don't have to put a big buffer
|
||||
// on the stack (as we don't have lots of memory lying around)
|
||||
for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++)
|
||||
{
|
||||
_dhcpUdpSocket.read(); // we don't care about the returned byte
|
||||
}
|
||||
|
||||
while (_dhcpUdpSocket.available() > 0)
|
||||
{
|
||||
switch (_dhcpUdpSocket.read())
|
||||
{
|
||||
case endOption :
|
||||
break;
|
||||
|
||||
case padOption :
|
||||
break;
|
||||
|
||||
case dhcpMessageType :
|
||||
opt_len = _dhcpUdpSocket.read();
|
||||
type = _dhcpUdpSocket.read();
|
||||
break;
|
||||
|
||||
case subnetMask :
|
||||
opt_len = _dhcpUdpSocket.read();
|
||||
_dhcpUdpSocket.read(_dhcpSubnetMask, 4);
|
||||
break;
|
||||
|
||||
case routersOnSubnet :
|
||||
opt_len = _dhcpUdpSocket.read();
|
||||
_dhcpUdpSocket.read(_dhcpGatewayIp, 4);
|
||||
for (int i = 0; i < opt_len-4; i++)
|
||||
{
|
||||
_dhcpUdpSocket.read();
|
||||
}
|
||||
break;
|
||||
|
||||
case dns :
|
||||
opt_len = _dhcpUdpSocket.read();
|
||||
_dhcpUdpSocket.read(_dhcpDnsServerIp, 4);
|
||||
for (int i = 0; i < opt_len-4; i++)
|
||||
{
|
||||
_dhcpUdpSocket.read();
|
||||
}
|
||||
break;
|
||||
|
||||
case dhcpServerIdentifier :
|
||||
opt_len = _dhcpUdpSocket.read();
|
||||
if( *((uint32_t*)_dhcpDhcpServerIp) == 0 ||
|
||||
IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() )
|
||||
{
|
||||
_dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip over the rest of this option
|
||||
while (opt_len--)
|
||||
{
|
||||
_dhcpUdpSocket.read();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case dhcpT1value :
|
||||
opt_len = _dhcpUdpSocket.read();
|
||||
_dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1));
|
||||
_dhcpT1 = ntohl(_dhcpT1);
|
||||
break;
|
||||
|
||||
case dhcpT2value :
|
||||
opt_len = _dhcpUdpSocket.read();
|
||||
_dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2));
|
||||
_dhcpT2 = ntohl(_dhcpT2);
|
||||
break;
|
||||
|
||||
case dhcpIPaddrLeaseTime :
|
||||
opt_len = _dhcpUdpSocket.read();
|
||||
_dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime));
|
||||
_dhcpLeaseTime = ntohl(_dhcpLeaseTime);
|
||||
_renewInSec = _dhcpLeaseTime;
|
||||
break;
|
||||
|
||||
default :
|
||||
opt_len = _dhcpUdpSocket.read();
|
||||
// Skip over the rest of this option
|
||||
while (opt_len--)
|
||||
{
|
||||
_dhcpUdpSocket.read();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Need to skip to end of the packet regardless here
|
||||
_dhcpUdpSocket.flush();
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
returns:
|
||||
0/DHCP_CHECK_NONE: nothing happened
|
||||
1/DHCP_CHECK_RENEW_FAIL: renew failed
|
||||
2/DHCP_CHECK_RENEW_OK: renew success
|
||||
3/DHCP_CHECK_REBIND_FAIL: rebind fail
|
||||
4/DHCP_CHECK_REBIND_OK: rebind success
|
||||
*/
|
||||
int DhcpClass::checkLease(){
|
||||
//this uses a signed / unsigned trick to deal with millis overflow
|
||||
unsigned long now = millis();
|
||||
signed long snow = (long)now;
|
||||
int rc=DHCP_CHECK_NONE;
|
||||
if (_lastCheck != 0){
|
||||
signed long factor;
|
||||
//calc how many ms past the timeout we are
|
||||
factor = snow - (long)_secTimeout;
|
||||
//if on or passed the timeout, reduce the counters
|
||||
if ( factor >= 0 ){
|
||||
//next timeout should be now plus 1000 ms minus parts of second in factor
|
||||
_secTimeout = snow + 1000 - factor % 1000;
|
||||
//how many seconds late are we, minimum 1
|
||||
factor = factor / 1000 +1;
|
||||
|
||||
//reduce the counters by that mouch
|
||||
//if we can assume that the cycle time (factor) is fairly constant
|
||||
//and if the remainder is less than cycle time * 2
|
||||
//do it early instead of late
|
||||
if(_renewInSec < factor*2 )
|
||||
_renewInSec = 0;
|
||||
else
|
||||
_renewInSec -= factor;
|
||||
|
||||
if(_rebindInSec < factor*2 )
|
||||
_rebindInSec = 0;
|
||||
else
|
||||
_rebindInSec -= factor;
|
||||
}
|
||||
|
||||
//if we have a lease but should renew, do it
|
||||
if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){
|
||||
_dhcp_state = STATE_DHCP_REREQUEST;
|
||||
rc = 1 + request_DHCP_lease();
|
||||
}
|
||||
|
||||
//if we have a lease or is renewing but should bind, do it
|
||||
if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){
|
||||
//this should basically restart completely
|
||||
_dhcp_state = STATE_DHCP_START;
|
||||
reset_DHCP_lease();
|
||||
rc = 3 + request_DHCP_lease();
|
||||
}
|
||||
}
|
||||
else{
|
||||
_secTimeout = snow + 1000;
|
||||
}
|
||||
|
||||
_lastCheck = now;
|
||||
return rc;
|
||||
}
|
||||
|
||||
IPAddress DhcpClass::getLocalIp()
|
||||
{
|
||||
return IPAddress(_dhcpLocalIp);
|
||||
}
|
||||
|
||||
IPAddress DhcpClass::getSubnetMask()
|
||||
{
|
||||
return IPAddress(_dhcpSubnetMask);
|
||||
}
|
||||
|
||||
IPAddress DhcpClass::getGatewayIp()
|
||||
{
|
||||
return IPAddress(_dhcpGatewayIp);
|
||||
}
|
||||
|
||||
IPAddress DhcpClass::getDhcpServerIp()
|
||||
{
|
||||
return IPAddress(_dhcpDhcpServerIp);
|
||||
}
|
||||
|
||||
IPAddress DhcpClass::getDnsServerIp()
|
||||
{
|
||||
return IPAddress(_dhcpDnsServerIp);
|
||||
}
|
||||
|
||||
void DhcpClass::printByte(char * buf, uint8_t n ) {
|
||||
char *str = &buf[1];
|
||||
buf[0]='0';
|
||||
do {
|
||||
unsigned long m = n;
|
||||
n /= 16;
|
||||
char c = m - 16 * n;
|
||||
*str-- = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while(n);
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
// DHCP Library v0.3 - April 25, 2009
|
||||
// Author: Jordan Terrell - blog.jordanterrell.com
|
||||
|
||||
#ifndef Dhcp_h
|
||||
#define Dhcp_h
|
||||
|
||||
#include "UIPUdp.h"
|
||||
|
||||
/* DHCP state machine. */
|
||||
#define STATE_DHCP_START 0
|
||||
#define STATE_DHCP_DISCOVER 1
|
||||
#define STATE_DHCP_REQUEST 2
|
||||
#define STATE_DHCP_LEASED 3
|
||||
#define STATE_DHCP_REREQUEST 4
|
||||
#define STATE_DHCP_RELEASE 5
|
||||
|
||||
#define DHCP_FLAGSBROADCAST 0x8000
|
||||
|
||||
/* UDP port numbers for DHCP */
|
||||
#define DHCP_SERVER_PORT 67 /* from server to client */
|
||||
#define DHCP_CLIENT_PORT 68 /* from client to server */
|
||||
|
||||
/* DHCP message OP code */
|
||||
#define DHCP_BOOTREQUEST 1
|
||||
#define DHCP_BOOTREPLY 2
|
||||
|
||||
/* DHCP message type */
|
||||
#define DHCP_DISCOVER 1
|
||||
#define DHCP_OFFER 2
|
||||
#define DHCP_REQUEST 3
|
||||
#define DHCP_DECLINE 4
|
||||
#define DHCP_ACK 5
|
||||
#define DHCP_NAK 6
|
||||
#define DHCP_RELEASE 7
|
||||
#define DHCP_INFORM 8
|
||||
|
||||
#define DHCP_HTYPE10MB 1
|
||||
#define DHCP_HTYPE100MB 2
|
||||
|
||||
#define DHCP_HLENETHERNET 6
|
||||
#define DHCP_HOPS 0
|
||||
#define DHCP_SECS 0
|
||||
|
||||
#define MAGIC_COOKIE 0x63825363
|
||||
#define MAX_DHCP_OPT 16
|
||||
|
||||
#define HOST_NAME "ENC28J"
|
||||
#define DEFAULT_LEASE (900) //default lease time in seconds
|
||||
|
||||
#define DHCP_CHECK_NONE (0)
|
||||
#define DHCP_CHECK_RENEW_FAIL (1)
|
||||
#define DHCP_CHECK_RENEW_OK (2)
|
||||
#define DHCP_CHECK_REBIND_FAIL (3)
|
||||
#define DHCP_CHECK_REBIND_OK (4)
|
||||
|
||||
enum
|
||||
{
|
||||
padOption = 0,
|
||||
subnetMask = 1,
|
||||
timerOffset = 2,
|
||||
routersOnSubnet = 3,
|
||||
/* timeServer = 4,
|
||||
nameServer = 5,*/
|
||||
dns = 6,
|
||||
/*logServer = 7,
|
||||
cookieServer = 8,
|
||||
lprServer = 9,
|
||||
impressServer = 10,
|
||||
resourceLocationServer = 11,*/
|
||||
hostName = 12,
|
||||
/*bootFileSize = 13,
|
||||
meritDumpFile = 14,*/
|
||||
domainName = 15,
|
||||
/*swapServer = 16,
|
||||
rootPath = 17,
|
||||
extentionsPath = 18,
|
||||
IPforwarding = 19,
|
||||
nonLocalSourceRouting = 20,
|
||||
policyFilter = 21,
|
||||
maxDgramReasmSize = 22,
|
||||
defaultIPTTL = 23,
|
||||
pathMTUagingTimeout = 24,
|
||||
pathMTUplateauTable = 25,
|
||||
ifMTU = 26,
|
||||
allSubnetsLocal = 27,
|
||||
broadcastAddr = 28,
|
||||
performMaskDiscovery = 29,
|
||||
maskSupplier = 30,
|
||||
performRouterDiscovery = 31,
|
||||
routerSolicitationAddr = 32,
|
||||
staticRoute = 33,
|
||||
trailerEncapsulation = 34,
|
||||
arpCacheTimeout = 35,
|
||||
ethernetEncapsulation = 36,
|
||||
tcpDefaultTTL = 37,
|
||||
tcpKeepaliveInterval = 38,
|
||||
tcpKeepaliveGarbage = 39,
|
||||
nisDomainName = 40,
|
||||
nisServers = 41,
|
||||
ntpServers = 42,
|
||||
vendorSpecificInfo = 43,
|
||||
netBIOSnameServer = 44,
|
||||
netBIOSdgramDistServer = 45,
|
||||
netBIOSnodeType = 46,
|
||||
netBIOSscope = 47,
|
||||
xFontServer = 48,
|
||||
xDisplayManager = 49,*/
|
||||
dhcpRequestedIPaddr = 50,
|
||||
dhcpIPaddrLeaseTime = 51,
|
||||
/*dhcpOptionOverload = 52,*/
|
||||
dhcpMessageType = 53,
|
||||
dhcpServerIdentifier = 54,
|
||||
dhcpParamRequest = 55,
|
||||
/*dhcpMsg = 56,
|
||||
dhcpMaxMsgSize = 57,*/
|
||||
dhcpT1value = 58,
|
||||
dhcpT2value = 59,
|
||||
/*dhcpClassIdentifier = 60,*/
|
||||
dhcpClientIdentifier = 61,
|
||||
endOption = 255
|
||||
};
|
||||
|
||||
typedef struct _RIP_MSG_FIXED
|
||||
{
|
||||
uint8_t op;
|
||||
uint8_t htype;
|
||||
uint8_t hlen;
|
||||
uint8_t hops;
|
||||
uint32_t xid;
|
||||
uint16_t secs;
|
||||
uint16_t flags;
|
||||
uint8_t ciaddr[4];
|
||||
uint8_t yiaddr[4];
|
||||
uint8_t siaddr[4];
|
||||
uint8_t giaddr[4];
|
||||
uint8_t chaddr[6];
|
||||
}RIP_MSG_FIXED;
|
||||
|
||||
class DhcpClass {
|
||||
private:
|
||||
uint32_t _dhcpInitialTransactionId;
|
||||
uint32_t _dhcpTransactionId;
|
||||
uint8_t _dhcpMacAddr[6];
|
||||
uint8_t _dhcpLocalIp[4];
|
||||
uint8_t _dhcpSubnetMask[4];
|
||||
uint8_t _dhcpGatewayIp[4];
|
||||
uint8_t _dhcpDhcpServerIp[4];
|
||||
uint8_t _dhcpDnsServerIp[4];
|
||||
uint32_t _dhcpLeaseTime;
|
||||
uint32_t _dhcpT1, _dhcpT2;
|
||||
signed long _renewInSec;
|
||||
signed long _rebindInSec;
|
||||
signed long _lastCheck;
|
||||
unsigned long _timeout;
|
||||
unsigned long _responseTimeout;
|
||||
unsigned long _secTimeout;
|
||||
uint8_t _dhcp_state;
|
||||
UIPUDP _dhcpUdpSocket;
|
||||
|
||||
int request_DHCP_lease();
|
||||
void reset_DHCP_lease();
|
||||
void presend_DHCP();
|
||||
void send_DHCP_MESSAGE(uint8_t, uint16_t);
|
||||
void printByte(char *, uint8_t);
|
||||
|
||||
uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId);
|
||||
public:
|
||||
IPAddress getLocalIp();
|
||||
IPAddress getSubnetMask();
|
||||
IPAddress getGatewayIp();
|
||||
IPAddress getDhcpServerIp();
|
||||
IPAddress getDnsServerIp();
|
||||
|
||||
int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
|
||||
int checkLease();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,422 +0,0 @@
|
||||
// Arduino DNS client for Enc28J60-based Ethernet shield
|
||||
// (c) Copyright 2009-2010 MCQN Ltd.
|
||||
// Released under Apache License, version 2.0
|
||||
|
||||
#include "Udp.h"
|
||||
#include "utility/util.h"
|
||||
|
||||
#include "Dns.h"
|
||||
#include <string.h>
|
||||
//#include <stdlib.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
#define SOCKET_NONE 255
|
||||
// Various flags and header field values for a DNS message
|
||||
#define UDP_HEADER_SIZE 8
|
||||
#define DNS_HEADER_SIZE 12
|
||||
#define TTL_SIZE 4
|
||||
#define QUERY_FLAG (0)
|
||||
#define RESPONSE_FLAG (1<<15)
|
||||
#define QUERY_RESPONSE_MASK (1<<15)
|
||||
#define OPCODE_STANDARD_QUERY (0)
|
||||
#define OPCODE_INVERSE_QUERY (1<<11)
|
||||
#define OPCODE_STATUS_REQUEST (2<<11)
|
||||
#define OPCODE_MASK (15<<11)
|
||||
#define AUTHORITATIVE_FLAG (1<<10)
|
||||
#define TRUNCATION_FLAG (1<<9)
|
||||
#define RECURSION_DESIRED_FLAG (1<<8)
|
||||
#define RECURSION_AVAILABLE_FLAG (1<<7)
|
||||
#define RESP_NO_ERROR (0)
|
||||
#define RESP_FORMAT_ERROR (1)
|
||||
#define RESP_SERVER_FAILURE (2)
|
||||
#define RESP_NAME_ERROR (3)
|
||||
#define RESP_NOT_IMPLEMENTED (4)
|
||||
#define RESP_REFUSED (5)
|
||||
#define RESP_MASK (15)
|
||||
#define TYPE_A (0x0001)
|
||||
#define CLASS_IN (0x0001)
|
||||
#define LABEL_COMPRESSION_MASK (0xC0)
|
||||
// Port number that DNS servers listen on
|
||||
#define DNS_PORT 53
|
||||
|
||||
// Possible return codes from ProcessResponse
|
||||
#define SUCCESS 1
|
||||
#define TIMED_OUT -1
|
||||
#define INVALID_SERVER -2
|
||||
#define TRUNCATED -3
|
||||
#define INVALID_RESPONSE -4
|
||||
|
||||
void DNSClient::begin(const IPAddress& aDNSServer)
|
||||
{
|
||||
iDNSServer = aDNSServer;
|
||||
iRequestId = 0;
|
||||
}
|
||||
|
||||
|
||||
int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult)
|
||||
{
|
||||
// See if we've been given a valid IP address
|
||||
const char* p =aIPAddrString;
|
||||
while (*p &&
|
||||
( (*p == '.') || (*p >= '0') || (*p <= '9') ))
|
||||
{
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == '\0')
|
||||
{
|
||||
// It's looking promising, we haven't found any invalid characters
|
||||
p = aIPAddrString;
|
||||
int segment =0;
|
||||
int segmentValue =0;
|
||||
while (*p && (segment < 4))
|
||||
{
|
||||
if (*p == '.')
|
||||
{
|
||||
// We've reached the end of a segment
|
||||
if (segmentValue > 255)
|
||||
{
|
||||
// You can't have IP address segments that don't fit in a byte
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
aResult[segment] = (byte)segmentValue;
|
||||
segment++;
|
||||
segmentValue = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Next digit
|
||||
segmentValue = (segmentValue*10)+(*p - '0');
|
||||
}
|
||||
p++;
|
||||
}
|
||||
// We've reached the end of address, but there'll still be the last
|
||||
// segment to deal with
|
||||
if ((segmentValue > 255) || (segment > 3))
|
||||
{
|
||||
// You can't have IP address segments that don't fit in a byte,
|
||||
// or more than four segments
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
aResult[segment] = (byte)segmentValue;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult)
|
||||
{
|
||||
int ret =0;
|
||||
|
||||
// See if it's a numeric IP address
|
||||
if (inet_aton(aHostname, aResult))
|
||||
{
|
||||
// It is, our work here is done
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check we've got a valid DNS server to use
|
||||
if (iDNSServer == INADDR_NONE)
|
||||
{
|
||||
return INVALID_SERVER;
|
||||
}
|
||||
|
||||
// Find a socket to use
|
||||
if (iUdp.begin(1024+(millis() & 0xF)) == 1)
|
||||
{
|
||||
// Try up to three times
|
||||
int retries = 0;
|
||||
// while ((retries < 3) && (ret <= 0))
|
||||
{
|
||||
// Send DNS request
|
||||
ret = iUdp.beginPacket(iDNSServer, DNS_PORT);
|
||||
if (ret != 0)
|
||||
{
|
||||
// Now output the request data
|
||||
ret = BuildRequest(aHostname);
|
||||
if (ret != 0)
|
||||
{
|
||||
// And finally send the request
|
||||
ret = iUdp.endPacket();
|
||||
if (ret != 0)
|
||||
{
|
||||
// Now wait for a response
|
||||
int wait_retries = 0;
|
||||
ret = TIMED_OUT;
|
||||
while ((wait_retries < 3) && (ret == TIMED_OUT))
|
||||
{
|
||||
ret = ProcessResponse(5000, aResult);
|
||||
wait_retries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
retries++;
|
||||
}
|
||||
|
||||
// We're done with the socket now
|
||||
iUdp.stop();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t DNSClient::BuildRequest(const char* aName)
|
||||
{
|
||||
// Build header
|
||||
// 1 1 1 1 1 1
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | ID |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | QDCOUNT |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | ANCOUNT |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | NSCOUNT |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | ARCOUNT |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// As we only support one request at a time at present, we can simplify
|
||||
// some of this header
|
||||
iRequestId = millis(); // generate a random ID
|
||||
uint16_t twoByteBuffer;
|
||||
|
||||
// FIXME We should also check that there's enough space available to write to, rather
|
||||
// FIXME than assume there's enough space (as the code does at present)
|
||||
iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId));
|
||||
|
||||
twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG);
|
||||
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
|
||||
|
||||
twoByteBuffer = htons(1); // One question record
|
||||
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
|
||||
|
||||
twoByteBuffer = 0; // Zero answer records
|
||||
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
|
||||
|
||||
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
|
||||
// and zero additional records
|
||||
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
|
||||
|
||||
// Build question
|
||||
const char* start =aName;
|
||||
const char* end =start;
|
||||
uint8_t len;
|
||||
// Run through the name being requested
|
||||
while (*end)
|
||||
{
|
||||
// Find out how long this section of the name is
|
||||
end = start;
|
||||
while (*end && (*end != '.') )
|
||||
{
|
||||
end++;
|
||||
}
|
||||
|
||||
if (end-start > 0)
|
||||
{
|
||||
// Write out the size of this section
|
||||
len = end-start;
|
||||
iUdp.write(&len, sizeof(len));
|
||||
// And then write out the section
|
||||
iUdp.write((uint8_t*)start, end-start);
|
||||
}
|
||||
start = end+1;
|
||||
}
|
||||
|
||||
// We've got to the end of the question name, so
|
||||
// terminate it with a zero-length section
|
||||
len = 0;
|
||||
iUdp.write(&len, sizeof(len));
|
||||
// Finally the type and class of question
|
||||
twoByteBuffer = htons(TYPE_A);
|
||||
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
|
||||
|
||||
twoByteBuffer = htons(CLASS_IN); // Internet class of question
|
||||
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
|
||||
// Success! Everything buffered okay
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress)
|
||||
{
|
||||
uint32_t startTime = millis();
|
||||
|
||||
// Wait for a response packet
|
||||
while(iUdp.parsePacket() <= 0)
|
||||
{
|
||||
if((millis() - startTime) > aTimeout)
|
||||
return TIMED_OUT;
|
||||
delay(50);
|
||||
}
|
||||
|
||||
// We've had a reply!
|
||||
// Read the UDP header
|
||||
uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header
|
||||
// Check that it's a response from the right server and the right port
|
||||
if ( (iDNSServer != iUdp.remoteIP()) ||
|
||||
(iUdp.remotePort() != DNS_PORT) )
|
||||
{
|
||||
// It's not from who we expected
|
||||
return INVALID_SERVER;
|
||||
}
|
||||
|
||||
// Read through the rest of the response
|
||||
if (iUdp.available() < DNS_HEADER_SIZE)
|
||||
{
|
||||
return TRUNCATED;
|
||||
}
|
||||
iUdp.read(header, DNS_HEADER_SIZE);
|
||||
|
||||
uint16_t header_flags = htons(*((uint16_t*)&header[2]));
|
||||
// Check that it's a response to this request
|
||||
if ( ( iRequestId != (*((uint16_t*)&header[0])) ) ||
|
||||
((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) )
|
||||
{
|
||||
// Mark the entire packet as read
|
||||
iUdp.flush();
|
||||
return INVALID_RESPONSE;
|
||||
}
|
||||
// Check for any errors in the response (or in our request)
|
||||
// although we don't do anything to get round these
|
||||
if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) )
|
||||
{
|
||||
// Mark the entire packet as read
|
||||
iUdp.flush();
|
||||
return -5; //INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// And make sure we've got (at least) one answer
|
||||
uint16_t answerCount = htons(*((uint16_t*)&header[6]));
|
||||
if (answerCount == 0 )
|
||||
{
|
||||
// Mark the entire packet as read
|
||||
iUdp.flush();
|
||||
return -6; //INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// Skip over any questions
|
||||
for (uint16_t i =0; i < htons(*((uint16_t*)&header[4])); i++)
|
||||
{
|
||||
// Skip over the name
|
||||
uint8_t len;
|
||||
do
|
||||
{
|
||||
iUdp.read(&len, sizeof(len));
|
||||
if (len > 0)
|
||||
{
|
||||
// Don't need to actually read the data out for the string, just
|
||||
// advance ptr to beyond it
|
||||
while(len--)
|
||||
{
|
||||
iUdp.read(); // we don't care about the returned byte
|
||||
}
|
||||
}
|
||||
} while (len != 0);
|
||||
|
||||
// Now jump over the type and class
|
||||
for (int i =0; i < 4; i++)
|
||||
{
|
||||
iUdp.read(); // we don't care about the returned byte
|
||||
}
|
||||
}
|
||||
|
||||
// Now we're up to the bit we're interested in, the answer
|
||||
// There might be more than one answer (although we'll just use the first
|
||||
// type A answer) and some authority and additional resource records but
|
||||
// we're going to ignore all of them.
|
||||
|
||||
for (uint16_t i =0; i < answerCount; i++)
|
||||
{
|
||||
// Skip the name
|
||||
uint8_t len;
|
||||
do
|
||||
{
|
||||
iUdp.read(&len, sizeof(len));
|
||||
if ((len & LABEL_COMPRESSION_MASK) == 0)
|
||||
{
|
||||
// It's just a normal label
|
||||
if (len > 0)
|
||||
{
|
||||
// And it's got a length
|
||||
// Don't need to actually read the data out for the string,
|
||||
// just advance ptr to beyond it
|
||||
while(len--)
|
||||
{
|
||||
iUdp.read(); // we don't care about the returned byte
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a pointer to a somewhere else in the message for the
|
||||
// rest of the name. We don't care about the name, and RFC1035
|
||||
// says that a name is either a sequence of labels ended with a
|
||||
// 0 length octet or a pointer or a sequence of labels ending in
|
||||
// a pointer. Either way, when we get here we're at the end of
|
||||
// the name
|
||||
// Skip over the pointer
|
||||
iUdp.read(); // we don't care about the returned byte
|
||||
// And set len so that we drop out of the name loop
|
||||
len = 0;
|
||||
}
|
||||
} while (len != 0);
|
||||
|
||||
// Check the type and class
|
||||
uint16_t answerType;
|
||||
uint16_t answerClass;
|
||||
iUdp.read((uint8_t*)&answerType, sizeof(answerType));
|
||||
iUdp.read((uint8_t*)&answerClass, sizeof(answerClass));
|
||||
|
||||
// Ignore the Time-To-Live as we don't do any caching
|
||||
for (int i =0; i < TTL_SIZE; i++)
|
||||
{
|
||||
iUdp.read(); // we don't care about the returned byte
|
||||
}
|
||||
|
||||
// And read out the length of this answer
|
||||
// Don't need header_flags anymore, so we can reuse it here
|
||||
iUdp.read((uint8_t*)&header_flags, sizeof(header_flags));
|
||||
|
||||
if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) )
|
||||
{
|
||||
if (htons(header_flags) != 4)
|
||||
{
|
||||
// It's a weird size
|
||||
// Mark the entire packet as read
|
||||
iUdp.flush();
|
||||
return -9;//INVALID_RESPONSE;
|
||||
}
|
||||
iUdp.read(aAddress.raw_address(), 4);
|
||||
return SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This isn't an answer type we're after, move onto the next one
|
||||
for (uint16_t i =0; i < htons(header_flags); i++)
|
||||
{
|
||||
iUdp.read(); // we don't care about the returned byte
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the entire packet as read
|
||||
iUdp.flush();
|
||||
|
||||
// If we get here then we haven't found an answer
|
||||
return -10;//INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
// Arduino DNS client for Enc28J60-based Ethernet shield
|
||||
// (c) Copyright 2009-2010 MCQN Ltd.
|
||||
// Released under Apache License, version 2.0
|
||||
|
||||
#ifndef DNSClient_h
|
||||
#define DNSClient_h
|
||||
|
||||
#include <UIPUdp.h>
|
||||
|
||||
class DNSClient
|
||||
{
|
||||
public:
|
||||
// ctor
|
||||
void begin(const IPAddress& aDNSServer);
|
||||
|
||||
/** Convert a numeric IP address string into a four-byte IP address.
|
||||
@param aIPAddrString IP address to convert
|
||||
@param aResult IPAddress structure to store the returned IP address
|
||||
@result 1 if aIPAddrString was successfully converted to an IP address,
|
||||
else error code
|
||||
*/
|
||||
int inet_aton(const char *aIPAddrString, IPAddress& aResult);
|
||||
|
||||
/** Resolve the given hostname to an IP address.
|
||||
@param aHostname Name to be resolved
|
||||
@param aResult IPAddress structure to store the returned IP address
|
||||
@result 1 if aIPAddrString was successfully converted to an IP address,
|
||||
else error code
|
||||
*/
|
||||
int getHostByName(const char* aHostname, IPAddress& aResult);
|
||||
|
||||
protected:
|
||||
uint16_t BuildRequest(const char* aName);
|
||||
uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress);
|
||||
|
||||
IPAddress iDNSServer;
|
||||
uint16_t iRequestId;
|
||||
UIPUDP iUdp;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,533 +0,0 @@
|
||||
/*
|
||||
UIPClient.cpp - Arduino implementation of a uIP wrapper class.
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#import "utility/uip-conf.h"
|
||||
#import "utility/uip.h"
|
||||
#import "utility/uip_arp.h"
|
||||
#import "string.h"
|
||||
}
|
||||
#include "UIPEthernet.h"
|
||||
#include "UIPClient.h"
|
||||
#include "Dns.h"
|
||||
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
#include "HardwareSerial.h"
|
||||
#endif
|
||||
|
||||
#define UIP_TCP_PHYH_LEN UIP_LLH_LEN+UIP_IPTCPH_LEN
|
||||
|
||||
uip_userdata_t UIPClient::all_data[UIP_CONNS];
|
||||
|
||||
UIPClient::UIPClient() :
|
||||
data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
UIPClient::UIPClient(uip_userdata_t* conn_data) :
|
||||
data(conn_data)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
UIPClient::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
uip_ipaddr_t ipaddr;
|
||||
uip_ip_addr(ipaddr, ip);
|
||||
struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
|
||||
if (conn)
|
||||
{
|
||||
while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
|
||||
{
|
||||
data = (uip_userdata_t*) conn->appstate;
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
|
||||
Serial.print(F("connected, state: "));
|
||||
Serial.print(data->state);
|
||||
Serial.print(F(", first packet in: "));
|
||||
Serial.println(data->packets_in[0]);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
UIPClient::connect(const char *host, uint16_t port)
|
||||
{
|
||||
// Look up the host first
|
||||
int ret = 0;
|
||||
#if UIP_UDP
|
||||
DNSClient dns;
|
||||
IPAddress remote_addr;
|
||||
|
||||
dns.begin(UIPEthernet.dnsServerIP());
|
||||
ret = dns.getHostByName(host, remote_addr);
|
||||
if (ret == 1) {
|
||||
return connect(remote_addr, port);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
UIPClient::stop()
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
_flushBlocks(&data->packets_in[0]);
|
||||
if (data->state & UIP_CLIENT_CLOSED)
|
||||
{
|
||||
data->state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
data->state |= UIP_CLIENT_CLOSE;
|
||||
}
|
||||
}
|
||||
data = NULL;
|
||||
UIPEthernet.tick();
|
||||
}
|
||||
|
||||
uint8_t
|
||||
UIPClient::connected()
|
||||
{
|
||||
return (data && (data->packets_in[0] != NOBLOCK || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0;
|
||||
}
|
||||
|
||||
bool
|
||||
UIPClient::operator==(const UIPClient& rhs)
|
||||
{
|
||||
return data && rhs.data && (data == rhs.data);
|
||||
}
|
||||
|
||||
UIPClient::operator bool()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
return data && (!(data->state & UIP_CLIENT_CLOSED) || data->packets_in[0] != NOBLOCK);
|
||||
}
|
||||
|
||||
size_t
|
||||
UIPClient::write(uint8_t c)
|
||||
{
|
||||
return _write(data, &c, 1);
|
||||
}
|
||||
|
||||
size_t
|
||||
UIPClient::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
return _write(data, buf, size);
|
||||
}
|
||||
|
||||
size_t
|
||||
UIPClient::_write(uip_userdata_t* u, const uint8_t *buf, size_t size)
|
||||
{
|
||||
int remain = size;
|
||||
uint16_t written;
|
||||
#if UIP_ATTEMPTS_ON_WRITE > 0
|
||||
uint16_t attempts = UIP_ATTEMPTS_ON_WRITE;
|
||||
#endif
|
||||
repeat:
|
||||
UIPEthernet.tick();
|
||||
if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED)))
|
||||
{
|
||||
memhandle* p = _currentBlock(&u->packets_out[0]);
|
||||
if (*p == NOBLOCK)
|
||||
{
|
||||
newpacket:
|
||||
*p = UIPEthernet.network.allocBlock(UIP_SOCKET_DATALEN);
|
||||
if (*p == NOBLOCK)
|
||||
{
|
||||
#if UIP_ATTEMPTS_ON_WRITE > 0
|
||||
if ((--attempts)>0)
|
||||
#endif
|
||||
#if UIP_ATTEMPTS_ON_WRITE != 0
|
||||
goto repeat;
|
||||
#endif
|
||||
goto ready;
|
||||
}
|
||||
u->out_pos = 0;
|
||||
}
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.print(F("UIPClient.write: writePacket("));
|
||||
Serial.print(*p);
|
||||
Serial.print(F(") pos: "));
|
||||
Serial.print(u->out_pos);
|
||||
Serial.print(F(", buf["));
|
||||
Serial.print(size-remain);
|
||||
Serial.print(F("-"));
|
||||
Serial.print(remain);
|
||||
Serial.print(F("]: '"));
|
||||
Serial.write((uint8_t*)buf+size-remain,remain);
|
||||
Serial.println(F("'"));
|
||||
#endif
|
||||
written = UIPEthernet.network.writePacket(*p,u->out_pos,(uint8_t*)buf+size-remain,remain);
|
||||
remain -= written;
|
||||
u->out_pos+=written;
|
||||
if (remain > 0)
|
||||
{
|
||||
if (p==&u->packets_out[UIP_SOCKET_NUMPACKETS-1])
|
||||
{
|
||||
#if UIP_ATTEMPTS_ON_WRITE > 0
|
||||
if ((--attempts)>0)
|
||||
#endif
|
||||
#if UIP_ATTEMPTS_ON_WRITE != 0
|
||||
goto repeat;
|
||||
#endif
|
||||
goto ready;
|
||||
}
|
||||
p++;
|
||||
goto newpacket;
|
||||
}
|
||||
ready:
|
||||
return size-remain;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
UIPClient::available()
|
||||
{
|
||||
if (*this)
|
||||
return _available(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
UIPClient::_available(uip_userdata_t *u)
|
||||
{
|
||||
memhandle* p = &u->packets_in[0];
|
||||
if (*p == NOBLOCK)
|
||||
return 0;
|
||||
int len = 0;
|
||||
for(memhandle* end = p+UIP_SOCKET_NUMPACKETS; p < end; p++)
|
||||
{
|
||||
if(*p == NOBLOCK)
|
||||
break;
|
||||
len += UIPEthernet.network.blockSize(*p);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
UIPClient::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
if (*this)
|
||||
{
|
||||
int remain = size;
|
||||
memhandle* p = &data->packets_in[0];
|
||||
if (*p == NOBLOCK)
|
||||
return 0;
|
||||
int read;
|
||||
do
|
||||
{
|
||||
read = UIPEthernet.network.readPacket(*p,0,buf+size-remain,remain);
|
||||
if (read == UIPEthernet.network.blockSize(*p))
|
||||
{
|
||||
remain -= read;
|
||||
_eatBlock(p);
|
||||
if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED)))
|
||||
data->state |= UIP_CLIENT_RESTART;
|
||||
if (*p == NOBLOCK)
|
||||
{
|
||||
if (data->state & UIP_CLIENT_CLOSED)
|
||||
{
|
||||
data->state = 0;
|
||||
data = NULL;
|
||||
}
|
||||
return size-remain;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UIPEthernet.network.resizeBlock(*p,read);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(remain > 0);
|
||||
return size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
UIPClient::read()
|
||||
{
|
||||
uint8_t c;
|
||||
if (read(&c,1) < 0)
|
||||
return -1;
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
UIPClient::peek()
|
||||
{
|
||||
if (*this)
|
||||
{
|
||||
memhandle p = data->packets_in[0];
|
||||
if (p != NOBLOCK)
|
||||
{
|
||||
uint8_t c;
|
||||
UIPEthernet.network.readPacket(p,0,&c,1);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
UIPClient::flush()
|
||||
{
|
||||
if (*this)
|
||||
{
|
||||
_flushBlocks(&data->packets_in[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
uipclient_appcall(void)
|
||||
{
|
||||
UIPClient::uip_callback();
|
||||
}
|
||||
|
||||
void
|
||||
UIPClient::uip_callback()
|
||||
{
|
||||
uip_userdata_t *u = (uip_userdata_t*)uip_conn->appstate;
|
||||
if (!u && uip_connected())
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("UIPClient uip_connected"));
|
||||
#endif
|
||||
u = (uip_userdata_t*) _allocateData();
|
||||
if (u)
|
||||
{
|
||||
uip_conn->appstate = u;
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.print(F("UIPClient allocated state: "));
|
||||
Serial.println(u->state);
|
||||
#endif
|
||||
}
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
else
|
||||
Serial.println(F("UIPClient allocation failed"));
|
||||
#endif
|
||||
}
|
||||
if (u)
|
||||
{
|
||||
if (uip_newdata())
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.print(F("UIPClient uip_newdata, uip_len:"));
|
||||
Serial.println(uip_len);
|
||||
#endif
|
||||
if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED)))
|
||||
{
|
||||
memhandle newPacket = UIPEthernet.network.allocBlock(uip_len);
|
||||
if (newPacket != NOBLOCK)
|
||||
{
|
||||
memhandle* p = _currentBlock(&u->packets_in[0]);
|
||||
//if it's not the first packet
|
||||
if (*p != NOBLOCK)
|
||||
{
|
||||
uint8_t slot = p - &u->packets_in[0];
|
||||
if (slot < UIP_SOCKET_NUMPACKETS-1)
|
||||
p++;
|
||||
//if this is the last slot stop this connection
|
||||
if (slot >= UIP_SOCKET_NUMPACKETS-2)
|
||||
{
|
||||
uip_stop();
|
||||
//if there's no free slot left omit loosing this packet and (again) stop this connection
|
||||
if (slot == UIP_SOCKET_NUMPACKETS-1)
|
||||
goto reject_newdata;
|
||||
}
|
||||
}
|
||||
UIPEthernet.network.copyPacket(newPacket,0,UIPEthernet.in_packet,((uint8_t*)uip_appdata)-uip_buf,uip_len);
|
||||
*p = newPacket;
|
||||
goto finish_newdata;
|
||||
}
|
||||
reject_newdata:
|
||||
UIPEthernet.packetstate &= ~UIPETHERNET_FREEPACKET;
|
||||
uip_stop();
|
||||
}
|
||||
}
|
||||
finish_newdata:
|
||||
if (u->state & UIP_CLIENT_RESTART)
|
||||
{
|
||||
u->state &= ~UIP_CLIENT_RESTART;
|
||||
uip_restart();
|
||||
}
|
||||
// If the connection has been closed, save received but unread data.
|
||||
if (uip_closed() || uip_timedout())
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("UIPClient uip_closed"));
|
||||
#endif
|
||||
// drop outgoing packets not sent yet:
|
||||
_flushBlocks(&u->packets_out[0]);
|
||||
if (u->packets_in[0] != NOBLOCK)
|
||||
{
|
||||
((uip_userdata_closed_t *)u)->lport = uip_conn->lport;
|
||||
u->state |= UIP_CLIENT_CLOSED;
|
||||
}
|
||||
else
|
||||
u->state = 0;
|
||||
// disassociate appdata.
|
||||
uip_conn->appstate = NULL;
|
||||
goto nodata;
|
||||
}
|
||||
if (uip_acked())
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.println(F("UIPClient uip_acked"));
|
||||
#endif
|
||||
_eatBlock(&u->packets_out[0]);
|
||||
}
|
||||
if (uip_poll() || uip_rexmit())
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
//Serial.println(F("UIPClient uip_poll"));
|
||||
#endif
|
||||
memhandle p = u->packets_out[0];
|
||||
if (p != NOBLOCK)
|
||||
{
|
||||
if (u->packets_out[1] == NOBLOCK)
|
||||
{
|
||||
uip_len = u->out_pos;
|
||||
if (uip_len > 0)
|
||||
{
|
||||
UIPEthernet.network.resizeBlock(p,0,uip_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
uip_len = UIPEthernet.network.blockSize(p);
|
||||
if (uip_len > 0)
|
||||
{
|
||||
UIPEthernet.uip_hdrlen = ((uint8_t*)uip_appdata)-uip_buf;
|
||||
UIPEthernet.uip_packet = UIPEthernet.network.allocBlock(UIPEthernet.uip_hdrlen+uip_len);
|
||||
if (UIPEthernet.uip_packet != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.copyPacket(UIPEthernet.uip_packet,UIPEthernet.uip_hdrlen,p,0,uip_len);
|
||||
UIPEthernet.packetstate |= UIPETHERNET_SENDPACKET;
|
||||
uip_send(uip_appdata,uip_len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// don't close connection unless all outgoing packets are sent
|
||||
if (u->state & UIP_CLIENT_CLOSE)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.print(F("UIPClient state UIP_CLIENT_CLOSE"));
|
||||
#endif
|
||||
if (u->packets_out[0] == NOBLOCK)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
Serial.print(F("UIPClient state UIP_CLIENT_CLOSE -> free userdata"));
|
||||
#endif
|
||||
u->state = 0;
|
||||
uip_conn->appstate = NULL;
|
||||
uip_close();
|
||||
}
|
||||
else
|
||||
uip_stop();
|
||||
}
|
||||
}
|
||||
nodata:
|
||||
UIPEthernet.uip_packet = NOBLOCK;
|
||||
uip_len=0;
|
||||
}
|
||||
|
||||
uip_userdata_t *
|
||||
UIPClient::_allocateData()
|
||||
{
|
||||
for ( uint8_t sock = 0; sock < UIP_CONNS; sock++ )
|
||||
{
|
||||
uip_userdata_t* data = &UIPClient::all_data[sock];
|
||||
if (!data->state)
|
||||
{
|
||||
data->state = sock | UIP_CLIENT_CONNECTED;
|
||||
memset(&data->packets_in[0],0,sizeof(uip_userdata_t)-sizeof(data->state));
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memhandle*
|
||||
UIPClient::_currentBlock(memhandle* block)
|
||||
{
|
||||
for(memhandle* end = block+UIP_SOCKET_NUMPACKETS-1; block < end; block++)
|
||||
if(*(block+1) == NOBLOCK)
|
||||
break;
|
||||
return block;
|
||||
}
|
||||
|
||||
void
|
||||
UIPClient::_eatBlock(memhandle* block)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
memhandle* start = block;
|
||||
Serial.print(F("eatblock("));
|
||||
Serial.print(*block);
|
||||
Serial.print("): ");
|
||||
for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++)
|
||||
{
|
||||
Serial.print(start[i]);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.print("-> ");
|
||||
#endif
|
||||
memhandle* end = block+(UIP_SOCKET_NUMPACKETS-1);
|
||||
UIPEthernet.network.freeBlock(*block);
|
||||
while(block < end)
|
||||
*block = *((block++)+1);
|
||||
*end = NOBLOCK;
|
||||
#ifdef UIPETHERNET_DEBUG_CLIENT
|
||||
for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++)
|
||||
{
|
||||
Serial.print(start[i]);
|
||||
Serial.print(F(" "));
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
UIPClient::_flushBlocks(memhandle* block)
|
||||
{
|
||||
for(memhandle* end = block+UIP_SOCKET_NUMPACKETS; block < end; block++)
|
||||
{
|
||||
if(*block != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(*block);
|
||||
*block = NOBLOCK;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
UIPClient.h - Arduino implementation of a uIP wrapper class.
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UIPCLIENT_H
|
||||
#define UIPCLIENT_H
|
||||
|
||||
#include "ethernet_comp.h"
|
||||
#import "Client.h"
|
||||
#import "utility/mempool.h"
|
||||
|
||||
extern "C" {
|
||||
#import "utility/uip.h"
|
||||
}
|
||||
|
||||
#define UIP_SOCKET_DATALEN UIP_TCP_MSS
|
||||
//#define UIP_SOCKET_NUMPACKETS UIP_RECEIVE_WINDOW/UIP_TCP_MSS+1
|
||||
#ifndef UIP_SOCKET_NUMPACKETS
|
||||
#define UIP_SOCKET_NUMPACKETS 5
|
||||
#endif
|
||||
|
||||
#define UIP_CLIENT_CONNECTED 0x10
|
||||
#define UIP_CLIENT_CLOSE 0x20
|
||||
#define UIP_CLIENT_CLOSED 0x40
|
||||
#define UIP_CLIENT_RESTART 0x80
|
||||
#define UIP_CLIENT_STATEFLAGS (UIP_CLIENT_CONNECTED | UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED | UIP_CLIENT_RESTART)
|
||||
#define UIP_CLIENT_SOCKETS ~UIP_CLIENT_STATEFLAGS
|
||||
|
||||
typedef uint8_t uip_socket_ptr;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
memhandle packets_in[UIP_SOCKET_NUMPACKETS];
|
||||
uint16_t lport; /**< The local TCP port, in network byte order. */
|
||||
} uip_userdata_closed_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
memhandle packets_in[UIP_SOCKET_NUMPACKETS];
|
||||
memhandle packets_out[UIP_SOCKET_NUMPACKETS];
|
||||
memaddress out_pos;
|
||||
} uip_userdata_t;
|
||||
|
||||
class UIPClient : public Client {
|
||||
|
||||
public:
|
||||
UIPClient();
|
||||
int connect(IPAddress ip, uint16_t port);
|
||||
int connect(const char *host, uint16_t port);
|
||||
int read(uint8_t *buf, size_t size);
|
||||
void stop();
|
||||
uint8_t connected();
|
||||
operator bool();
|
||||
virtual bool operator==(const EthernetClient&);
|
||||
virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); };
|
||||
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *buf, size_t size);
|
||||
int available();
|
||||
int read();
|
||||
int peek();
|
||||
void flush();
|
||||
|
||||
private:
|
||||
UIPClient(struct uip_conn *_conn);
|
||||
UIPClient(uip_userdata_t* conn_data);
|
||||
|
||||
uip_userdata_t* data;
|
||||
|
||||
static uip_userdata_t all_data[UIP_CONNS];
|
||||
static uip_userdata_t* _allocateData();
|
||||
static uip_userdata_t* _getData(struct uip_conn * conn);
|
||||
|
||||
static size_t _write(uip_userdata_t *,const uint8_t *buf, size_t size);
|
||||
static int _available(uip_userdata_t *);
|
||||
|
||||
static memhandle * _currentBlock(memhandle* blocks);
|
||||
static void _eatBlock(memhandle* blocks);
|
||||
static void _flushBlocks(memhandle* blocks);
|
||||
|
||||
friend class UIPEthernetClass;
|
||||
friend class UIPServer;
|
||||
|
||||
friend void uipclient_appcall(void);
|
||||
|
||||
static void uip_callback();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,433 +0,0 @@
|
||||
/*
|
||||
UIPEthernet.cpp - Arduino implementation of a uIP wrapper class.
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "UIPEthernet.h"
|
||||
#include "utility/Enc28J60Network.h"
|
||||
|
||||
#if(defined UIPETHERNET_DEBUG || defined UIPETHERNET_DEBUG_CHKSUM)
|
||||
#include "HardwareSerial.h"
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "utility/uip-conf.h"
|
||||
#include "utility/uip.h"
|
||||
#include "utility/uip_arp.h"
|
||||
#include "utility/uip_timer.h"
|
||||
}
|
||||
|
||||
#define ETH_HDR ((struct uip_eth_hdr *)&uip_buf[0])
|
||||
|
||||
// Because uIP isn't encapsulated within a class we have to use global
|
||||
// variables, so we can only have one TCP/IP stack per program.
|
||||
|
||||
UIPEthernetClass::UIPEthernetClass() :
|
||||
in_packet(NOBLOCK),
|
||||
uip_packet(NOBLOCK),
|
||||
uip_hdrlen(0),
|
||||
packetstate(0),
|
||||
_dhcp(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
UIPEthernetClass::begin(const uint8_t* mac)
|
||||
{
|
||||
static DhcpClass s_dhcp;
|
||||
_dhcp = &s_dhcp;
|
||||
|
||||
// Initialise the basic info
|
||||
init(mac);
|
||||
|
||||
// Now try to get our config info from a DHCP server
|
||||
int ret = _dhcp->beginWithDHCP((uint8_t*)mac);
|
||||
if(ret == 1)
|
||||
{
|
||||
// We've successfully found a DHCP server and got our configuration info, so set things
|
||||
// accordingly
|
||||
configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip)
|
||||
{
|
||||
IPAddress dns = ip;
|
||||
dns[3] = 1;
|
||||
begin(mac, ip, dns);
|
||||
}
|
||||
|
||||
void
|
||||
UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns)
|
||||
{
|
||||
IPAddress gateway = ip;
|
||||
gateway[3] = 1;
|
||||
begin(mac, ip, dns, gateway);
|
||||
}
|
||||
|
||||
void
|
||||
UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway)
|
||||
{
|
||||
IPAddress subnet(255, 255, 255, 0);
|
||||
begin(mac, ip, dns, gateway, subnet);
|
||||
}
|
||||
|
||||
void
|
||||
UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet)
|
||||
{
|
||||
init(mac);
|
||||
configure(ip,dns,gateway,subnet);
|
||||
}
|
||||
|
||||
int UIPEthernetClass::maintain(){
|
||||
tick();
|
||||
int rc = DHCP_CHECK_NONE;
|
||||
if(_dhcp != NULL){
|
||||
//we have a pointer to dhcp, use it
|
||||
rc = _dhcp->checkLease();
|
||||
switch ( rc ){
|
||||
case DHCP_CHECK_NONE:
|
||||
//nothing done
|
||||
break;
|
||||
case DHCP_CHECK_RENEW_OK:
|
||||
case DHCP_CHECK_REBIND_OK:
|
||||
//we might have got a new IP.
|
||||
configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask());
|
||||
break;
|
||||
default:
|
||||
//this is actually a error, it will retry though
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
IPAddress UIPEthernetClass::localIP()
|
||||
{
|
||||
IPAddress ret;
|
||||
uip_ipaddr_t a;
|
||||
uip_gethostaddr(a);
|
||||
return ip_addr_uip(a);
|
||||
}
|
||||
|
||||
IPAddress UIPEthernetClass::subnetMask()
|
||||
{
|
||||
IPAddress ret;
|
||||
uip_ipaddr_t a;
|
||||
uip_getnetmask(a);
|
||||
return ip_addr_uip(a);
|
||||
}
|
||||
|
||||
IPAddress UIPEthernetClass::gatewayIP()
|
||||
{
|
||||
IPAddress ret;
|
||||
uip_ipaddr_t a;
|
||||
uip_getdraddr(a);
|
||||
return ip_addr_uip(a);
|
||||
}
|
||||
|
||||
IPAddress UIPEthernetClass::dnsServerIP()
|
||||
{
|
||||
return _dnsServerAddress;
|
||||
}
|
||||
|
||||
void
|
||||
UIPEthernetClass::tick()
|
||||
{
|
||||
if (in_packet == NOBLOCK)
|
||||
{
|
||||
in_packet = network.receivePacket();
|
||||
#ifdef UIPETHERNET_DEBUG
|
||||
if (in_packet != NOBLOCK)
|
||||
{
|
||||
Serial.print(F("--------------\nreceivePacket: "));
|
||||
Serial.println(in_packet);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (in_packet != NOBLOCK)
|
||||
{
|
||||
packetstate = UIPETHERNET_FREEPACKET;
|
||||
uip_len = network.blockSize(in_packet);
|
||||
if (uip_len > 0)
|
||||
{
|
||||
network.readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE);
|
||||
if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP))
|
||||
{
|
||||
uip_packet = in_packet;
|
||||
#ifdef UIPETHERNET_DEBUG
|
||||
Serial.print(F("readPacket type IP, uip_len: "));
|
||||
Serial.println(uip_len);
|
||||
#endif
|
||||
uip_arp_ipin();
|
||||
uip_input();
|
||||
if (uip_len > 0)
|
||||
{
|
||||
uip_arp_out();
|
||||
network_send();
|
||||
}
|
||||
}
|
||||
else if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_ARP))
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG
|
||||
Serial.print(F("readPacket type ARP, uip_len: "));
|
||||
Serial.println(uip_len);
|
||||
#endif
|
||||
uip_arp_arpin();
|
||||
if (uip_len > 0)
|
||||
{
|
||||
network_send();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET))
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG
|
||||
Serial.print(F("freeing packet: "));
|
||||
Serial.println(in_packet);
|
||||
#endif
|
||||
network.freePacket();
|
||||
in_packet = NOBLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
if (uip_timer_expired(&periodic_timer))
|
||||
{
|
||||
uip_timer_restart(&periodic_timer);
|
||||
for (int i = 0; i < UIP_CONNS; i++)
|
||||
{
|
||||
uip_periodic(i);
|
||||
// If the above function invocation resulted in data that
|
||||
// should be sent out on the network, the global variable
|
||||
// uip_len is set to a value > 0.
|
||||
if (uip_len > 0)
|
||||
{
|
||||
uip_arp_out();
|
||||
network_send();
|
||||
}
|
||||
}
|
||||
|
||||
#if UIP_UDP
|
||||
for (int i = 0; i < UIP_UDP_CONNS; i++)
|
||||
{
|
||||
uip_udp_periodic(i);
|
||||
// If the above function invocation resulted in data that
|
||||
// should be sent out on the network, the global variable
|
||||
// uip_len is set to a value > 0. */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
network_send();
|
||||
}
|
||||
}
|
||||
#endif /* UIP_UDP */
|
||||
}
|
||||
}
|
||||
|
||||
boolean UIPEthernetClass::network_send()
|
||||
{
|
||||
if (packetstate & UIPETHERNET_SENDPACKET)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG
|
||||
Serial.print(F("network_send uip_packet: "));
|
||||
Serial.print(uip_packet);
|
||||
Serial.print(F(", hdrlen: "));
|
||||
Serial.println(uip_hdrlen);
|
||||
#endif
|
||||
network.writePacket(uip_packet,0,uip_buf,uip_hdrlen);
|
||||
goto sendandfree;
|
||||
}
|
||||
uip_packet = network.allocBlock(uip_len);
|
||||
if (uip_packet != NOBLOCK)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG
|
||||
Serial.print(F("network_send uip_buf (uip_len): "));
|
||||
Serial.print(uip_len);
|
||||
Serial.print(F(", packet: "));
|
||||
Serial.println(uip_packet);
|
||||
#endif
|
||||
network.writePacket(uip_packet,0,uip_buf,uip_len);
|
||||
goto sendandfree;
|
||||
}
|
||||
return false;
|
||||
sendandfree:
|
||||
network.sendPacket(uip_packet);
|
||||
network.freeBlock(uip_packet);
|
||||
uip_packet = NOBLOCK;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIPEthernetClass::init(const uint8_t* mac) {
|
||||
uip_timer_set(&this->periodic_timer, CLOCK_SECOND / 4);
|
||||
|
||||
network.init((uint8_t*)mac);
|
||||
uip_seteth_addr(mac);
|
||||
|
||||
uip_init();
|
||||
}
|
||||
|
||||
void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) {
|
||||
uip_ipaddr_t ipaddr;
|
||||
|
||||
uip_ip_addr(ipaddr, ip);
|
||||
uip_sethostaddr(ipaddr);
|
||||
|
||||
uip_ip_addr(ipaddr, gateway);
|
||||
uip_setdraddr(ipaddr);
|
||||
|
||||
uip_ip_addr(ipaddr, subnet);
|
||||
uip_setnetmask(ipaddr);
|
||||
|
||||
_dnsServerAddress = dns;
|
||||
}
|
||||
|
||||
UIPEthernetClass UIPEthernet;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint16_t
|
||||
UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint16_t t;
|
||||
const uint8_t *dataptr;
|
||||
const uint8_t *last_byte;
|
||||
|
||||
dataptr = data;
|
||||
last_byte = data + len - 1;
|
||||
|
||||
while(dataptr < last_byte) { /* At least two more bytes */
|
||||
t = (dataptr[0] << 8) + dataptr[1];
|
||||
sum += t;
|
||||
if(sum < t) {
|
||||
sum++; /* carry */
|
||||
}
|
||||
dataptr += 2;
|
||||
}
|
||||
|
||||
if(dataptr == last_byte) {
|
||||
t = (dataptr[0] << 8) + 0;
|
||||
sum += t;
|
||||
if(sum < t) {
|
||||
sum++; /* carry */
|
||||
}
|
||||
}
|
||||
|
||||
/* Return sum in host byte order. */
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
uint16_t
|
||||
UIPEthernetClass::ipchksum(void)
|
||||
{
|
||||
uint16_t sum;
|
||||
|
||||
sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
|
||||
return (sum == 0) ? 0xffff : htons(sum);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint16_t
|
||||
UIPEthernetClass::upper_layer_chksum(uint8_t proto)
|
||||
{
|
||||
uint16_t upper_layer_len;
|
||||
uint16_t sum;
|
||||
|
||||
#if UIP_CONF_IPV6
|
||||
upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]);
|
||||
#else /* UIP_CONF_IPV6 */
|
||||
upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
/* First sum pseudoheader. */
|
||||
|
||||
/* IP protocol and length fields. This addition cannot carry. */
|
||||
sum = upper_layer_len + proto;
|
||||
/* Sum IP source and destination addresses. */
|
||||
sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
|
||||
|
||||
uint8_t upper_layer_memlen;
|
||||
switch(proto)
|
||||
{
|
||||
case UIP_PROTO_ICMP:
|
||||
case UIP_PROTO_ICMP6:
|
||||
upper_layer_memlen = upper_layer_len;
|
||||
break;
|
||||
case UIP_PROTO_TCP:
|
||||
upper_layer_memlen = (BUF->tcpoffset >> 4) << 2;
|
||||
break;
|
||||
#if UIP_UDP
|
||||
case UIP_PROTO_UDP:
|
||||
upper_layer_memlen = UIP_UDPH_LEN;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen);
|
||||
#ifdef UIPETHERNET_DEBUG_CHKSUM
|
||||
Serial.print(F("chksum uip_buf["));
|
||||
Serial.print(UIP_IPH_LEN + UIP_LLH_LEN);
|
||||
Serial.print(F("-"));
|
||||
Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen);
|
||||
Serial.print(F("]: "));
|
||||
Serial.println(htons(sum),HEX);
|
||||
#endif
|
||||
if (upper_layer_memlen < upper_layer_len)
|
||||
{
|
||||
sum = network.chksum(
|
||||
sum,
|
||||
uip_packet,
|
||||
UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen,
|
||||
upper_layer_len - upper_layer_memlen
|
||||
);
|
||||
#ifdef UIPETHERNET_DEBUG_CHKSUM
|
||||
Serial.print(F("chksum uip_packet("));
|
||||
Serial.print(uip_packet);
|
||||
Serial.print(F(")["));
|
||||
Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen);
|
||||
Serial.print(F("-"));
|
||||
Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len);
|
||||
Serial.print(F"]: "));
|
||||
Serial.println(htons(sum),HEX);
|
||||
#endif
|
||||
}
|
||||
return (sum == 0) ? 0xffff : htons(sum);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
uip_ipchksum(void)
|
||||
{
|
||||
return UIPEthernet.ipchksum();
|
||||
}
|
||||
|
||||
uint16_t
|
||||
uip_tcpchksum(void)
|
||||
{
|
||||
uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP);
|
||||
return sum;
|
||||
}
|
||||
|
||||
#if UIP_UDP
|
||||
uint16_t
|
||||
uip_udpchksum(void)
|
||||
{
|
||||
uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP);
|
||||
return sum;
|
||||
}
|
||||
#endif
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
UIPEthernet.h - Arduino implementation of a uIP wrapper class.
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UIPETHERNET_H
|
||||
#define UIPETHERNET_H
|
||||
|
||||
#include "ethernet_comp.h"
|
||||
#include <Arduino.h>
|
||||
#include "Dhcp.h"
|
||||
#include "IPAddress.h"
|
||||
#include "utility/Enc28J60Network.h"
|
||||
#include "UIPClient.h"
|
||||
#include "UIPServer.h"
|
||||
#include "UIPUdp.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "utility/uip_timer.h"
|
||||
#include "utility/uip.h"
|
||||
}
|
||||
|
||||
//#define UIPETHERNET_DEBUG
|
||||
//#define UIPETHERNET_DEBUG_CHKSUM
|
||||
//#define UIPETHERNET_DEBUG_UDP
|
||||
//#define UIPETHERNET_DEBUG_CLIENT
|
||||
|
||||
#define UIPETHERNET_FREEPACKET 1
|
||||
#define UIPETHERNET_SENDPACKET 2
|
||||
#define UIPETHERNET_BUFFERREAD 4
|
||||
|
||||
#define uip_ip_addr(addr, ip) do { \
|
||||
((u16_t *)(addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \
|
||||
((u16_t *)(addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \
|
||||
} while(0)
|
||||
|
||||
#define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8 , a[1] & 0xFF, a[1] >> 8) //TODO this is not IPV6 capable
|
||||
|
||||
#define uip_seteth_addr(eaddr) do {uip_ethaddr.addr[0] = eaddr[0]; \
|
||||
uip_ethaddr.addr[1] = eaddr[1];\
|
||||
uip_ethaddr.addr[2] = eaddr[2];\
|
||||
uip_ethaddr.addr[3] = eaddr[3];\
|
||||
uip_ethaddr.addr[4] = eaddr[4];\
|
||||
uip_ethaddr.addr[5] = eaddr[5];} while(0)
|
||||
|
||||
#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
|
||||
class UIPEthernetClass
|
||||
{
|
||||
public:
|
||||
UIPEthernetClass();
|
||||
|
||||
int begin(const uint8_t* mac);
|
||||
void begin(const uint8_t* mac, IPAddress ip);
|
||||
void begin(const uint8_t* mac, IPAddress ip, IPAddress dns);
|
||||
void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway);
|
||||
void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);
|
||||
|
||||
// maintain() must be called at regular intervals to process the incoming serial
|
||||
// data and issue IP events to the sketch. It does not return until all IP
|
||||
// events have been processed. Renews dhcp-lease if required.
|
||||
int maintain();
|
||||
|
||||
IPAddress localIP();
|
||||
IPAddress subnetMask();
|
||||
IPAddress gatewayIP();
|
||||
IPAddress dnsServerIP();
|
||||
|
||||
private:
|
||||
IPAddress _dnsServerAddress;
|
||||
DhcpClass* _dhcp;
|
||||
|
||||
struct uip_timer periodic_timer;
|
||||
|
||||
memhandle in_packet;
|
||||
memhandle uip_packet;
|
||||
uint8_t uip_hdrlen;
|
||||
uint8_t packetstate;
|
||||
|
||||
Enc28J60Network network;
|
||||
|
||||
void init(const uint8_t* mac);
|
||||
void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);
|
||||
|
||||
void tick();
|
||||
|
||||
boolean network_send();
|
||||
|
||||
friend class UIPServer;
|
||||
|
||||
friend class UIPClient;
|
||||
|
||||
friend class UIPUDP;
|
||||
|
||||
static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len);
|
||||
static uint16_t ipchksum(void);
|
||||
uint16_t upper_layer_chksum(uint8_t proto);
|
||||
|
||||
friend uint16_t uip_ipchksum(void);
|
||||
friend uint16_t uip_tcpchksum(void);
|
||||
friend uint16_t uip_udpchksum(void);
|
||||
|
||||
#if UIP_CONF_IPV6
|
||||
uint16_t uip_icmp6chksum(void);
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
};
|
||||
|
||||
extern UIPEthernetClass UIPEthernet;
|
||||
|
||||
#endif
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
UIPServer.cpp - Arduino implementation of a uIP wrapper class.
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "UIPEthernet.h"
|
||||
#include "UIPServer.h"
|
||||
extern "C" {
|
||||
#include "utility/uip-conf.h"
|
||||
}
|
||||
|
||||
UIPServer::UIPServer(uint16_t port) : _port(htons(port))
|
||||
{
|
||||
}
|
||||
|
||||
UIPClient UIPServer::available()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
for ( uip_userdata_t* data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++ )
|
||||
{
|
||||
if (data->packets_in[0] != NOBLOCK
|
||||
&& (((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport ==_port)
|
||||
|| ((data->state & UIP_CLIENT_CLOSED) && ((uip_userdata_closed_t *)data)->lport == _port)))
|
||||
return UIPClient(data);
|
||||
}
|
||||
return UIPClient();
|
||||
}
|
||||
|
||||
void UIPServer::begin()
|
||||
{
|
||||
uip_listen(_port);
|
||||
UIPEthernet.tick();
|
||||
}
|
||||
|
||||
size_t UIPServer::write(uint8_t c)
|
||||
{
|
||||
return write(&c,1);
|
||||
}
|
||||
|
||||
size_t UIPServer::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t ret = 0;
|
||||
for ( uip_userdata_t* data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++ )
|
||||
{
|
||||
if ((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport ==_port)
|
||||
ret += UIPClient::_write(data,buf,size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
UIPServer.h - Arduino implementation of a uIP wrapper class.
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef UIPSERVER_H
|
||||
#define UIPSERVER_H
|
||||
|
||||
#include "ethernet_comp.h"
|
||||
#import "Server.h"
|
||||
#import "UIPClient.h"
|
||||
|
||||
class UIPServer : Server {
|
||||
|
||||
public:
|
||||
UIPServer(uint16_t);
|
||||
UIPClient available();
|
||||
void begin();
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *buf, size_t size);
|
||||
using Print::write;
|
||||
|
||||
private:
|
||||
uint16_t _port;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,424 +0,0 @@
|
||||
/*
|
||||
UIPUdp.cpp - Arduino implementation of a uIP wrapper class.
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "UIPEthernet.h"
|
||||
#include "UIPUdp.h"
|
||||
#include "Dns.h"
|
||||
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
#include "HardwareSerial.h"
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "utility/uip-conf.h"
|
||||
#include "utility/uip.h"
|
||||
#include "utility/uip_arp.h"
|
||||
}
|
||||
|
||||
#if UIP_UDP
|
||||
#define UIP_ARPHDRSIZE 42
|
||||
#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
|
||||
// Constructor
|
||||
UIPUDP::UIPUDP() :
|
||||
_uip_udp_conn(NULL)
|
||||
{
|
||||
memset(&appdata,0,sizeof(appdata));
|
||||
}
|
||||
|
||||
// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||
uint8_t
|
||||
UIPUDP::begin(uint16_t port)
|
||||
{
|
||||
if (!_uip_udp_conn)
|
||||
{
|
||||
_uip_udp_conn = uip_udp_new(NULL, 0);
|
||||
}
|
||||
if (_uip_udp_conn)
|
||||
{
|
||||
uip_udp_bind(_uip_udp_conn,htons(port));
|
||||
_uip_udp_conn->appstate = &appdata;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Finish with the UDP socket
|
||||
void
|
||||
UIPUDP::stop()
|
||||
{
|
||||
if (_uip_udp_conn)
|
||||
{
|
||||
flush();
|
||||
uip_udp_remove(_uip_udp_conn);
|
||||
_uip_udp_conn->appstate = NULL;
|
||||
_uip_udp_conn=NULL;
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(appdata.packet_in);
|
||||
appdata.packet_in = NOBLOCK;
|
||||
}
|
||||
uint8_t i = 0;
|
||||
memhandle* packet = &appdata.packets_in[0];
|
||||
while (*packet != NOBLOCK && i < UIP_UDP_NUMPACKETS)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(*packet);
|
||||
*packet++ = NOBLOCK;
|
||||
i++;
|
||||
}
|
||||
if (appdata.packet_out != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(appdata.packet_out);
|
||||
appdata.packet_out = NOBLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sending UDP packets
|
||||
|
||||
// Start building up a packet to send to the remote host specific in ip and port
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
int
|
||||
UIPUDP::beginPacket(IPAddress ip, uint16_t port)
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
if (ip && port)
|
||||
{
|
||||
uip_ipaddr_t ripaddr;
|
||||
uip_ip_addr(&ripaddr, ip);
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp beginPacket, "));
|
||||
#endif
|
||||
if (_uip_udp_conn)
|
||||
{
|
||||
_uip_udp_conn->rport = htons(port);
|
||||
uip_ipaddr_copy(_uip_udp_conn->ripaddr, &ripaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
_uip_udp_conn = uip_udp_new(&ripaddr,htons(port));
|
||||
if (_uip_udp_conn)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("new connection, "));
|
||||
#endif
|
||||
_uip_udp_conn->appstate = &appdata;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.println(F("failed to allocate new connection"));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("rip: "));
|
||||
Serial.print(ip);
|
||||
Serial.print(F(", port: "));
|
||||
Serial.println(port);
|
||||
#endif
|
||||
}
|
||||
if (_uip_udp_conn)
|
||||
{
|
||||
if (appdata.packet_out == NOBLOCK)
|
||||
{
|
||||
appdata.packet_out = UIPEthernet.network.allocBlock(UIP_UDP_MAXPACKETSIZE);
|
||||
appdata.out_pos = UIP_UDP_PHYH_LEN;
|
||||
if (appdata.packet_out != NOBLOCK)
|
||||
return 1;
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
else
|
||||
Serial.println(F("failed to allocate memory for packet"));
|
||||
#endif
|
||||
}
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
else
|
||||
Serial.println(F("previous packet on that connection not sent yet"));
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start building up a packet to send to the remote host specific in host and port
|
||||
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||
int
|
||||
UIPUDP::beginPacket(const char *host, uint16_t port)
|
||||
{
|
||||
// Look up the host first
|
||||
int ret = 0;
|
||||
DNSClient dns;
|
||||
IPAddress remote_addr;
|
||||
|
||||
dns.begin(UIPEthernet.dnsServerIP());
|
||||
ret = dns.getHostByName(host, remote_addr);
|
||||
if (ret == 1) {
|
||||
return beginPacket(remote_addr, port);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// Finish off this packet and send it
|
||||
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||
int
|
||||
UIPUDP::endPacket()
|
||||
{
|
||||
if (_uip_udp_conn && appdata.packet_out != NOBLOCK)
|
||||
{
|
||||
appdata.send = true;
|
||||
UIPEthernet.network.resizeBlock(appdata.packet_out,0,appdata.out_pos);
|
||||
uip_udp_periodic_conn(_uip_udp_conn);
|
||||
if (uip_len > 0)
|
||||
{
|
||||
UIPEthernet.network_send();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write a single byte into the packet
|
||||
size_t
|
||||
UIPUDP::write(uint8_t c)
|
||||
{
|
||||
return write(&c,1);
|
||||
}
|
||||
|
||||
// Write size bytes from buffer into the packet
|
||||
size_t
|
||||
UIPUDP::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
if (appdata.packet_out != NOBLOCK)
|
||||
{
|
||||
size_t ret = UIPEthernet.network.writePacket(appdata.packet_out,appdata.out_pos,(uint8_t*)buffer,size);
|
||||
appdata.out_pos += ret;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start processing the next available incoming packet
|
||||
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||
int
|
||||
UIPUDP::parsePacket()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp parsePacket freeing previous packet: "));
|
||||
Serial.println(appdata.packet_in);
|
||||
#endif;
|
||||
UIPEthernet.network.freeBlock(appdata.packet_in);
|
||||
}
|
||||
memhandle *packet = &appdata.packets_in[0];
|
||||
appdata.packet_in = *packet;
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp parsePacket received packet: "));
|
||||
Serial.print(appdata.packet_in);
|
||||
#endif
|
||||
if (UIP_UDP_NUMPACKETS > 1)
|
||||
{
|
||||
uint8_t i = 1;
|
||||
memhandle* p = packet+1;
|
||||
freeloop:
|
||||
*packet = *p;
|
||||
if (*packet == NOBLOCK)
|
||||
goto freeready;
|
||||
packet++;
|
||||
if (i < UIP_UDP_NUMPACKETS-1)
|
||||
{
|
||||
i++;
|
||||
p++;
|
||||
goto freeloop;
|
||||
}
|
||||
}
|
||||
*packet = NOBLOCK;
|
||||
freeready:
|
||||
int size = UIPEthernet.network.blockSize(appdata.packet_in);
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F(", size: "));
|
||||
Serial.println(size);
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Number of bytes remaining in the current packet
|
||||
int
|
||||
UIPUDP::available()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
return UIPEthernet.network.blockSize(appdata.packet_in);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read a single byte from the current packet
|
||||
int
|
||||
UIPUDP::read()
|
||||
{
|
||||
unsigned char c;
|
||||
if (read(&c,1) > 0)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Read up to len bytes from the current packet and place them into buffer
|
||||
// Returns the number of bytes read, or 0 if none are available
|
||||
int
|
||||
UIPUDP::read(unsigned char* buffer, size_t len)
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
int read = UIPEthernet.network.readPacket(appdata.packet_in,0,buffer,len);
|
||||
UIPEthernet.network.resizeBlock(appdata.packet_in,read);
|
||||
return read;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Return the next byte from the current packet without moving on to the next byte
|
||||
int
|
||||
UIPUDP::peek()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
unsigned char c;
|
||||
if (UIPEthernet.network.readPacket(appdata.packet_in,0,&c,1) == 1)
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Finish reading the current packet
|
||||
void
|
||||
UIPUDP::flush()
|
||||
{
|
||||
UIPEthernet.tick();
|
||||
if (appdata.packet_in != NOBLOCK)
|
||||
{
|
||||
UIPEthernet.network.freeBlock(appdata.packet_in);
|
||||
appdata.packet_in = NOBLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the IP address of the host who sent the current incoming packet
|
||||
IPAddress
|
||||
UIPUDP::remoteIP()
|
||||
{
|
||||
return _uip_udp_conn ? ip_addr_uip(_uip_udp_conn->ripaddr) : IPAddress();
|
||||
}
|
||||
|
||||
// Return the port of the host who sent the current incoming packet
|
||||
uint16_t
|
||||
UIPUDP::remotePort()
|
||||
{
|
||||
return _uip_udp_conn ? ntohs(_uip_udp_conn->rport) : 0;
|
||||
}
|
||||
|
||||
// uIP callback function
|
||||
|
||||
void
|
||||
uipudp_appcall(void) {
|
||||
UIPUDP::uip_callback();
|
||||
}
|
||||
|
||||
void
|
||||
UIPUDP::uip_callback() {
|
||||
if (appdata_t *data = (appdata_t *)(uip_udp_conn->appstate))
|
||||
{
|
||||
if (uip_newdata())
|
||||
{
|
||||
uip_udp_conn->rport = UDPBUF->srcport;
|
||||
uip_ipaddr_copy(uip_udp_conn->ripaddr,UDPBUF->srcipaddr);
|
||||
memhandle *packet = &data->packets_in[0];
|
||||
uint8_t i = 0;
|
||||
do
|
||||
{
|
||||
if (*packet == NOBLOCK)
|
||||
{
|
||||
*packet = UIPEthernet.network.allocBlock(ntohs(UDPBUF->udplen)-UIP_UDPH_LEN);
|
||||
//if we are unable to allocate memory the packet is dropped. udp doesn't guarantee packet delivery
|
||||
if (*packet != NOBLOCK)
|
||||
{
|
||||
//discard Linklevel and IP and udp-header and any trailing bytes:
|
||||
UIPEthernet.network.copyPacket(*packet,0,UIPEthernet.in_packet,UIP_UDP_PHYH_LEN,UIPEthernet.network.blockSize(*packet));
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp, uip_newdata received packet: "));
|
||||
Serial.print(*packet);
|
||||
Serial.print(F(", slot: "));
|
||||
Serial.print(i);
|
||||
Serial.print(F(", size: "));
|
||||
Serial.println(UIPEthernet.network.blockSize(*packet));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
packet++;
|
||||
i++;
|
||||
}
|
||||
while (i < UIP_UDP_NUMPACKETS);
|
||||
}
|
||||
if (uip_poll() && data->send)
|
||||
{
|
||||
//set uip_slen (uip private) by calling uip_udp_send
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp, uip_poll preparing packet to send: "));
|
||||
Serial.print(data->packet_out);
|
||||
Serial.print(F(", size: "));
|
||||
Serial.println(UIPEthernet.network.blockSize(data->packet_out));
|
||||
#endif
|
||||
UIPEthernet.uip_packet = data->packet_out;
|
||||
data->packet_out = NOBLOCK;
|
||||
UIPEthernet.uip_hdrlen = UIP_UDP_PHYH_LEN;
|
||||
UIPEthernet.packetstate |= UIPETHERNET_SENDPACKET;
|
||||
uip_udp_send(data->out_pos - (UIP_UDP_PHYH_LEN));
|
||||
uip_process(UIP_UDP_SEND_CONN); //generate udp + ip headers
|
||||
uip_arp_out(); //add arp
|
||||
if (uip_len == UIP_ARPHDRSIZE)
|
||||
{
|
||||
UIPEthernet.packetstate &= ~UIPETHERNET_SENDPACKET;
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.println(F("udp, uip_poll results in ARP-packet"));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
//arp found ethaddr for ip (otherwise packet is replaced by arp-request)
|
||||
{
|
||||
data->send = false;
|
||||
#ifdef UIPETHERNET_DEBUG_UDP
|
||||
Serial.print(F("udp, uip_packet to send: "));
|
||||
Serial.println(UIPEthernet.uip_packet);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
UIPUdp.h - Arduino implementation of a uIP wrapper class.
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UIPUDP_H
|
||||
#define UIPUDP_H
|
||||
|
||||
#include "ethernet_comp.h"
|
||||
#include "Arduino.h"
|
||||
#include <Udp.h>
|
||||
#include "utility/mempool.h"
|
||||
extern "C" {
|
||||
#include "utility/uip.h";
|
||||
}
|
||||
|
||||
#define UIP_UDP_MAXDATALEN 1500
|
||||
#define UIP_UDP_PHYH_LEN UIP_LLH_LEN+UIP_IPUDPH_LEN
|
||||
#define UIP_UDP_MAXPACKETSIZE UIP_UDP_MAXDATALEN+UIP_UDP_PHYH_LEN
|
||||
#ifndef UIP_UDP_NUMPACKETS
|
||||
#define UIP_UDP_NUMPACKETS 5
|
||||
#endif
|
||||
|
||||
class UIPUDP : public UDP
|
||||
{
|
||||
|
||||
private:
|
||||
struct uip_udp_conn *_uip_udp_conn;
|
||||
|
||||
struct appdata_t
|
||||
{
|
||||
memaddress out_pos;
|
||||
memhandle packets_in[UIP_UDP_NUMPACKETS];
|
||||
memhandle packet_in;
|
||||
memhandle packet_out;
|
||||
boolean send;
|
||||
} appdata;
|
||||
|
||||
public:
|
||||
UIPUDP(); // Constructor
|
||||
uint8_t
|
||||
begin(uint16_t);// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||
void
|
||||
stop(); // Finish with the UDP socket
|
||||
|
||||
// Sending UDP packets
|
||||
|
||||
// Start building up a packet to send to the remote host specific in ip and port
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
int
|
||||
beginPacket(IPAddress ip, uint16_t port);
|
||||
// Start building up a packet to send to the remote host specific in host and port
|
||||
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||
int
|
||||
beginPacket(const char *host, uint16_t port);
|
||||
// Finish off this packet and send it
|
||||
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||
int
|
||||
endPacket();
|
||||
// Write a single byte into the packet
|
||||
size_t
|
||||
write(uint8_t);
|
||||
// Write size bytes from buffer into the packet
|
||||
size_t
|
||||
write(const uint8_t *buffer, size_t size);
|
||||
|
||||
using Print::write;
|
||||
|
||||
// Start processing the next available incoming packet
|
||||
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||
int
|
||||
parsePacket();
|
||||
// Number of bytes remaining in the current packet
|
||||
int
|
||||
available();
|
||||
// Read a single byte from the current packet
|
||||
int
|
||||
read();
|
||||
// Read up to len bytes from the current packet and place them into buffer
|
||||
// Returns the number of bytes read, or 0 if none are available
|
||||
int
|
||||
read(unsigned char* buffer, size_t len);
|
||||
// Read up to len characters from the current packet and place them into buffer
|
||||
// Returns the number of characters read, or 0 if none are available
|
||||
int
|
||||
read(char* buffer, size_t len)
|
||||
{
|
||||
return read((unsigned char*) buffer, len);
|
||||
}
|
||||
;
|
||||
// Return the next byte from the current packet without moving on to the next byte
|
||||
int
|
||||
peek();
|
||||
void
|
||||
flush(); // Finish reading the current packet
|
||||
|
||||
// Return the IP address of the host who sent the current incoming packet
|
||||
IPAddress
|
||||
remoteIP();
|
||||
|
||||
// Return the port of the host who sent the current incoming packet
|
||||
uint16_t
|
||||
remotePort();
|
||||
|
||||
private:
|
||||
|
||||
friend void uipudp_appcall(void);
|
||||
|
||||
static void uip_callback();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,9 +0,0 @@
|
||||
#ifndef ETHERNET_COMP_H
|
||||
#define ETHERNET_COMP_H
|
||||
|
||||
#define Ethernet UIPEthernet
|
||||
#define EthernetClient UIPClient
|
||||
#define EthernetServer UIPServer
|
||||
#define EthernetUDP UIPUDP
|
||||
|
||||
#endif
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
Enc28J60Network.h
|
||||
UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface.
|
||||
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
inspired by enc28j60.c file from the AVRlib library by Pascal Stang.
|
||||
For AVRlib See http://www.procyonengineering.com/
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ENC28J60NETWORK_H_
|
||||
#define ENC28J60NETWORK_H_
|
||||
|
||||
#include "mempool.h"
|
||||
|
||||
#define ENC28J60_CONTROL_CS SS // this is pin 10 on Uno and pin 53 on Mega256
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
// AVR-specific code
|
||||
#define SPI_MOSI MOSI
|
||||
#define SPI_MISO MISO
|
||||
#define SPI_SCK SCK
|
||||
#define SPI_SS SS
|
||||
#define ENC28J60_USE_SPILIB 0
|
||||
#elif defined(ARDUINO_ARCH_SAM)
|
||||
#define ENC28J60_USE_SPILIB 1
|
||||
#endif
|
||||
|
||||
#define UIP_RECEIVEBUFFERHANDLE 0xff
|
||||
|
||||
//#define ENC28J60DEBUG
|
||||
|
||||
/*
|
||||
* Empfangen von ip-header, arp etc...
|
||||
* wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection
|
||||
*/
|
||||
|
||||
class Enc28J60Network : public MemoryPool
|
||||
{
|
||||
|
||||
private:
|
||||
uint16_t nextPacketPtr;
|
||||
uint8_t bank;
|
||||
|
||||
struct memblock receivePkt;
|
||||
|
||||
uint8_t readOp(uint8_t op, uint8_t address);
|
||||
void writeOp(uint8_t op, uint8_t address, uint8_t data);
|
||||
uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len);
|
||||
void setERXRDPT();
|
||||
void readBuffer(uint16_t len, uint8_t* data);
|
||||
void writeBuffer(uint16_t len, uint8_t* data);
|
||||
uint8_t readByte(uint16_t addr);
|
||||
void writeByte(uint16_t addr, uint8_t data);
|
||||
void setBank(uint8_t address);
|
||||
uint8_t readReg(uint8_t address);
|
||||
void writeReg(uint8_t address, uint8_t data);
|
||||
void writeRegPair(uint8_t address, uint16_t data);
|
||||
void phyWrite(uint8_t address, uint16_t data);
|
||||
void clkout(uint8_t clk);
|
||||
uint8_t getrev(void);
|
||||
|
||||
protected:
|
||||
void memblock_mv_cb(memaddress dest, memaddress src, memaddress size);
|
||||
|
||||
public:
|
||||
Enc28J60Network();
|
||||
void init(uint8_t* macaddr);
|
||||
memhandle receivePacket();
|
||||
void freePacket();
|
||||
memaddress blockSize(memhandle handle);
|
||||
void sendPacket(memhandle handle);
|
||||
uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len);
|
||||
uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len);
|
||||
void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len);
|
||||
uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len);
|
||||
};
|
||||
|
||||
#endif /* ENC28J60NETWORK_H_ */
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef MEMPOOLCONF_H
|
||||
#define MEMPOOLCONF_H
|
||||
#include "uipethernet-conf.h"
|
||||
extern "C" {
|
||||
#include "uipopt.h"
|
||||
}
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef uint16_t memaddress;
|
||||
typedef uint8_t memhandle;
|
||||
|
||||
#if UIP_SOCKET_NUMPACKETS and UIP_CONNS
|
||||
#define NUM_TCP_MEMBLOCKS (UIP_SOCKET_NUMPACKETS*2)*UIP_CONNS
|
||||
#else
|
||||
#define NUM_TCP_MEMBLOCKS 0
|
||||
#endif
|
||||
|
||||
#if UIP_UDP and UIP_UDP_NUMPACKETS and UIP_UDP_CONNS
|
||||
#define NUM_UDP_MEMBLOCKS (UIP_UDP_NUMPACKETS+1)*UIP_UDP_CONNS
|
||||
#else
|
||||
#define NUM_UDP_MEMBLOCKS 0
|
||||
#endif
|
||||
|
||||
#define NUM_MEMBLOCKS (NUM_TCP_MEMBLOCKS+NUM_UDP_MEMBLOCKS)
|
||||
|
||||
#define MEMBLOCK_MV
|
||||
|
||||
#endif
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* $Id: uip-neighbor.c,v 1.2 2006/06/12 08:00:30 adam Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Database of link-local neighbors, used by IPv6 code and
|
||||
* to be used by a future ARP code rewrite.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
#include "uip-neighbor.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_TIME 128
|
||||
|
||||
#ifdef UIP_NEIGHBOR_CONF_ENTRIES
|
||||
#define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES
|
||||
#else /* UIP_NEIGHBOR_CONF_ENTRIES */
|
||||
#define ENTRIES 8
|
||||
#endif /* UIP_NEIGHBOR_CONF_ENTRIES */
|
||||
|
||||
struct neighbor_entry {
|
||||
uip_ipaddr_t ipaddr;
|
||||
struct uip_neighbor_addr addr;
|
||||
u8_t time;
|
||||
};
|
||||
static struct neighbor_entry entries[ENTRIES];
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ENTRIES; ++i) {
|
||||
entries[i].time = MAX_TIME;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_periodic(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ENTRIES; ++i) {
|
||||
if(entries[i].time < MAX_TIME) {
|
||||
entries[i].time++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr)
|
||||
{
|
||||
int i, oldest;
|
||||
u8_t oldest_time;
|
||||
|
||||
printf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3],
|
||||
addr->addr.addr[4], addr->addr.addr[5]);
|
||||
|
||||
/* Find the first unused entry or the oldest used entry. */
|
||||
oldest_time = 0;
|
||||
oldest = 0;
|
||||
for(i = 0; i < ENTRIES; ++i) {
|
||||
if(entries[i].time == MAX_TIME) {
|
||||
oldest = i;
|
||||
break;
|
||||
}
|
||||
if(uip_ipaddr_cmp(entries[i].ipaddr, addr)) {
|
||||
oldest = i;
|
||||
break;
|
||||
}
|
||||
if(entries[i].time > oldest_time) {
|
||||
oldest = i;
|
||||
oldest_time = entries[i].time;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use the oldest or first free entry (either pointed to by the
|
||||
"oldest" variable). */
|
||||
entries[oldest].time = 0;
|
||||
uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr);
|
||||
memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct neighbor_entry *
|
||||
find_entry(uip_ipaddr_t ipaddr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ENTRIES; ++i) {
|
||||
if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) {
|
||||
return &entries[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_update(uip_ipaddr_t ipaddr)
|
||||
{
|
||||
struct neighbor_entry *e;
|
||||
|
||||
e = find_entry(ipaddr);
|
||||
if(e != NULL) {
|
||||
e->time = 0;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct uip_neighbor_addr *
|
||||
uip_neighbor_lookup(uip_ipaddr_t ipaddr)
|
||||
{
|
||||
struct neighbor_entry *e;
|
||||
|
||||
e = find_entry(ipaddr);
|
||||
if(e != NULL) {
|
||||
/* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3],
|
||||
e->addr.addr.addr[4], e->addr.addr.addr[5]);*/
|
||||
|
||||
return &e->addr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* $Id: uip-neighbor.h,v 1.2 2006/06/12 08:00:30 adam Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Header file for database of link-local neighbors, used by
|
||||
* IPv6 code and to be used by future ARP code.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __UIP_NEIGHBOR_H__
|
||||
#define __UIP_NEIGHBOR_H__
|
||||
|
||||
#include "uip.h"
|
||||
|
||||
struct uip_neighbor_addr {
|
||||
#if UIP_NEIGHBOR_CONF_ADDRTYPE
|
||||
UIP_NEIGHBOR_CONF_ADDRTYPE addr;
|
||||
#else
|
||||
struct uip_eth_addr addr;
|
||||
#endif
|
||||
};
|
||||
|
||||
void uip_neighbor_init(void);
|
||||
void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr);
|
||||
void uip_neighbor_update(uip_ipaddr_t ipaddr);
|
||||
struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr);
|
||||
void uip_neighbor_periodic(void);
|
||||
|
||||
#endif /* __UIP-NEIGHBOR_H__ */
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef UIPETHERNET_CONF_H
|
||||
#define UIPETHERNET_CONF_H
|
||||
|
||||
/* for TCP */
|
||||
#define UIP_SOCKET_NUMPACKETS 5
|
||||
#define UIP_CONF_MAX_CONNECTIONS 4
|
||||
|
||||
/* for UDP */
|
||||
#define UIP_CONF_UDP 0//1
|
||||
#define UIP_CONF_BROADCAST 0//1
|
||||
#define UIP_CONF_UDP_CONNS 0//4
|
||||
#define UIP_UDP_NUMPACKETS 0//5
|
||||
|
||||
/* number of attempts on write before returning number of bytes sent so far
|
||||
* set to -1 to block until connection is closed by timeout */
|
||||
#define UIP_ATTEMPTS_ON_WRITE -1
|
||||
|
||||
#endif
|
||||
+68
-121
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Enc28J60Network.h
|
||||
Enc28J60NetworkClass.h
|
||||
UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface.
|
||||
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
@@ -25,19 +25,8 @@
|
||||
#include "Enc28J60Network.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
#if ENC28J60_USE_SPILIB
|
||||
#include <SPI.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
// AVR-specific code
|
||||
#include <avr/io.h>
|
||||
#elif defined(ARDUINO_ARCH_SAM)
|
||||
// SAM-specific code
|
||||
#else
|
||||
// generic, non-platform specific code
|
||||
#endif
|
||||
#include <avr/io.h>
|
||||
#include "enc28j60.h"
|
||||
#include "uip.h"
|
||||
}
|
||||
@@ -51,57 +40,40 @@ extern "C" {
|
||||
// set CS to 1 = passive
|
||||
#define CSPASSIVE digitalWrite(ENC28J60_CONTROL_CS, HIGH)
|
||||
//
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
#define waitspi() while(!(SPSR&(1<<SPIF)))
|
||||
#elif defined(ARDUINO_ARCH_SAM)
|
||||
#if ENC28J60_CONTROL_CS==BOARD_SPI_SS0 or ENC28J60_CONTROL_CS==BOARD_SPI_SS1 or ENC28J60_CONTROL_CS==BOARD_SPI_SS2 or ENC28J60_CONTROL_CS==BOARD_SPI_SS3
|
||||
#define ENC28J60_USE_SPILIB_EXT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint16_t Enc28J60Network::nextPacketPtr;
|
||||
uint8_t Enc28J60Network::bank=0xff;
|
||||
|
||||
|
||||
Enc28J60Network::Enc28J60Network() :
|
||||
MemoryPool(TXSTART_INIT+1, TXSTOP_INIT-TXSTART_INIT), // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte
|
||||
bank(0xff)
|
||||
{
|
||||
}
|
||||
struct memblock Enc28J60Network::receivePkt;
|
||||
|
||||
void Enc28J60Network::init(uint8_t* macaddr)
|
||||
{
|
||||
MemoryPool::init(); // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte
|
||||
// initialize I/O
|
||||
// ss as output:
|
||||
pinMode(ENC28J60_CONTROL_CS, OUTPUT);
|
||||
CSPASSIVE; // ss=0
|
||||
//
|
||||
|
||||
#if ENC28J60_USE_SPILIB
|
||||
SPI.begin();
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
// AVR-specific code
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV2); //results in 8MHZ at 16MHZ system clock.
|
||||
#elif defined(ARDUINO_ARCH_SAM)
|
||||
// SAM-specific code
|
||||
SPI.setClockDivider(10); //defaults to 21 which results in aprox. 4MHZ. A 10 should result in a little more than 8MHZ.
|
||||
#else
|
||||
// generic, non-platform specific code
|
||||
#endif
|
||||
#else
|
||||
pinMode(SPI_MOSI, OUTPUT);
|
||||
pinMode(SPI_SCK, OUTPUT);
|
||||
pinMode(SPI_MISO, INPUT);
|
||||
//Hardware SS must be configured as OUTPUT to enable SPI-master (regardless of which pin is configured as ENC28J60_CONTROL_CS)
|
||||
pinMode(SPI_SS, OUTPUT);
|
||||
|
||||
digitalWrite(SPI_MOSI, LOW);
|
||||
digitalWrite(SPI_SCK, LOW);
|
||||
|
||||
/*DDRB |= 1<<PB3 | 1<<PB5; // mosi, sck output
|
||||
cbi(DDRB,PINB4); // MISO is input
|
||||
//
|
||||
cbi(PORTB,PB3); // MOSI low
|
||||
cbi(PORTB,PB5); // SCK low
|
||||
*/
|
||||
//
|
||||
// initialize SPI interface
|
||||
// master mode and Fosc/2 clock:
|
||||
SPCR = (1<<SPE)|(1<<MSTR);
|
||||
SPSR |= (1<<SPI2X);
|
||||
#endif
|
||||
|
||||
// perform system reset
|
||||
writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
|
||||
delay(50);
|
||||
@@ -176,7 +148,7 @@ void Enc28J60Network::init(uint8_t* macaddr)
|
||||
memhandle
|
||||
Enc28J60Network::receivePacket()
|
||||
{
|
||||
uint16_t rxstat;
|
||||
uint8_t rxstat;
|
||||
uint16_t len;
|
||||
// check if a packet has been received and buffered
|
||||
//if( !(readReg(EIR) & EIR_PKTIF) ){
|
||||
@@ -195,7 +167,7 @@ Enc28J60Network::receivePacket()
|
||||
len -= 4; //remove the CRC count
|
||||
// read the receive status (see datasheet page 43)
|
||||
rxstat = readOp(ENC28J60_READ_BUF_MEM, 0);
|
||||
rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
|
||||
//rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
|
||||
// decrement the packet counter indicate we are done with this packet
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
|
||||
// check CRC and symbol errors (see datasheet page 44, table 7-3):
|
||||
@@ -223,7 +195,7 @@ Enc28J60Network::setERXRDPT()
|
||||
memaddress
|
||||
Enc28J60Network::blockSize(memhandle handle)
|
||||
{
|
||||
return handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size;
|
||||
return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -312,14 +284,6 @@ uint8_t Enc28J60Network::readByte(uint16_t addr)
|
||||
writeRegPair(ERDPTL, addr);
|
||||
|
||||
CSACTIVE;
|
||||
#if ENC28J60_USE_SPILIB
|
||||
// issue read command
|
||||
SPI.transfer(ENC28J60_READ_BUF_MEM);
|
||||
// read data
|
||||
uint8_t c = SPI.transfer(0x00);
|
||||
CSPASSIVE;
|
||||
return (c);
|
||||
#else
|
||||
// issue read command
|
||||
SPDR = ENC28J60_READ_BUF_MEM;
|
||||
waitspi();
|
||||
@@ -328,7 +292,6 @@ uint8_t Enc28J60Network::readByte(uint16_t addr)
|
||||
waitspi();
|
||||
CSPASSIVE;
|
||||
return (SPDR);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Enc28J60Network::writeByte(uint16_t addr, uint8_t data)
|
||||
@@ -336,19 +299,12 @@ void Enc28J60Network::writeByte(uint16_t addr, uint8_t data)
|
||||
writeRegPair(EWRPTL, addr);
|
||||
|
||||
CSACTIVE;
|
||||
#if ENC28J60_USE_SPILIB
|
||||
// issue write command
|
||||
SPI.transfer(ENC28J60_WRITE_BUF_MEM);
|
||||
// write data
|
||||
SPI.transfer(data);
|
||||
#else
|
||||
// issue write command
|
||||
SPDR = ENC28J60_WRITE_BUF_MEM;
|
||||
waitspi();
|
||||
// write data
|
||||
SPDR = data;
|
||||
waitspi();
|
||||
#endif
|
||||
CSPASSIVE;
|
||||
}
|
||||
|
||||
@@ -357,19 +313,22 @@ Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle s
|
||||
{
|
||||
memblock *dest = &blocks[dest_pkt];
|
||||
memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt];
|
||||
memblock_mv_cb(dest->begin+dest_pos,src->begin+src_pos,len);
|
||||
enc28J60_mempool_block_move_callback(dest->begin+dest_pos,src->begin+src_pos,len);
|
||||
// Move the RX read pointer to the start of the next received packet
|
||||
// This frees the memory we just read out
|
||||
setERXRDPT();
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len)
|
||||
enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len)
|
||||
{
|
||||
//void
|
||||
//Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len)
|
||||
//{
|
||||
//as ENC28J60 DMA is unable to copy single bytes:
|
||||
if (len == 1)
|
||||
{
|
||||
writeByte(dest,readByte(src));
|
||||
Enc28J60Network::writeByte(dest,Enc28J60Network::readByte(src));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -390,11 +349,11 @@ Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len)
|
||||
prevent a never ending DMA operation which
|
||||
would overwrite the entire 8-Kbyte buffer.
|
||||
*/
|
||||
writeRegPair(EDMASTL, src);
|
||||
writeRegPair(EDMADSTL, dest);
|
||||
Enc28J60Network::writeRegPair(EDMASTL, src);
|
||||
Enc28J60Network::writeRegPair(EDMADSTL, dest);
|
||||
|
||||
if ((src <= RXSTOP_INIT)&& (len > RXSTOP_INIT))len -= (RXSTOP_INIT-RXSTART_INIT);
|
||||
writeRegPair(EDMANDL, len);
|
||||
Enc28J60Network::writeRegPair(EDMANDL, len);
|
||||
|
||||
/*
|
||||
2. If an interrupt at the end of the copy process is
|
||||
@@ -402,13 +361,13 @@ Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len)
|
||||
clear EIR.DMAIF.
|
||||
|
||||
3. Verify that ECON1.CSUMEN is clear. */
|
||||
writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN);
|
||||
Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN);
|
||||
|
||||
/* 4. Start the DMA copy by setting ECON1.DMAST. */
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST);
|
||||
Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST);
|
||||
|
||||
// wait until runnig DMA is completed
|
||||
while (readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST);
|
||||
while (Enc28J60Network::readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,20 +382,6 @@ Enc28J60Network::readOp(uint8_t op, uint8_t address)
|
||||
{
|
||||
CSACTIVE;
|
||||
// issue read command
|
||||
#if ENC28J60_USE_SPILIB
|
||||
SPI.transfer(op | (address & ADDR_MASK));
|
||||
// read data
|
||||
if(address & 0x80)
|
||||
{
|
||||
// do dummy read if needed (for mac and mii, see datasheet page 29)
|
||||
SPI.transfer(0x00);
|
||||
}
|
||||
uint8_t c = SPI.transfer(0x00);
|
||||
// release CS
|
||||
CSPASSIVE;
|
||||
return(c);
|
||||
#else
|
||||
// issue read command
|
||||
SPDR = op | (address & ADDR_MASK);
|
||||
waitspi();
|
||||
// read data
|
||||
@@ -451,7 +396,6 @@ Enc28J60Network::readOp(uint8_t op, uint8_t address)
|
||||
// release CS
|
||||
CSPASSIVE;
|
||||
return(SPDR);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@@ -459,18 +403,11 @@ Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data)
|
||||
{
|
||||
CSACTIVE;
|
||||
// issue write command
|
||||
#if ENC28J60_USE_SPILIB
|
||||
SPI.transfer(op | (address & ADDR_MASK));
|
||||
// write data
|
||||
SPI.transfer(data);
|
||||
#else
|
||||
// issue write command
|
||||
SPDR = op | (address & ADDR_MASK);
|
||||
waitspi();
|
||||
// write data
|
||||
SPDR = data;
|
||||
waitspi();
|
||||
#endif
|
||||
CSPASSIVE;
|
||||
}
|
||||
|
||||
@@ -479,23 +416,15 @@ Enc28J60Network::readBuffer(uint16_t len, uint8_t* data)
|
||||
{
|
||||
CSACTIVE;
|
||||
// issue read command
|
||||
#if ENC28J60_USE_SPILIB
|
||||
SPI.transfer(ENC28J60_READ_BUF_MEM);
|
||||
#else
|
||||
SPDR = ENC28J60_READ_BUF_MEM;
|
||||
waitspi();
|
||||
#endif
|
||||
while(len)
|
||||
{
|
||||
len--;
|
||||
// read data
|
||||
#if ENC28J60_USE_SPILIB
|
||||
*data = SPI.transfer(0x00);
|
||||
#else
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
*data = SPDR;
|
||||
#endif
|
||||
data++;
|
||||
}
|
||||
//*data='\0';
|
||||
@@ -507,24 +436,15 @@ Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data)
|
||||
{
|
||||
CSACTIVE;
|
||||
// issue write command
|
||||
#if ENC28J60_USE_SPILIB
|
||||
SPI.transfer(ENC28J60_WRITE_BUF_MEM);
|
||||
#else
|
||||
SPDR = ENC28J60_WRITE_BUF_MEM;
|
||||
waitspi();
|
||||
#endif
|
||||
while(len)
|
||||
{
|
||||
len--;
|
||||
// write data
|
||||
#if ENC28J60_USE_SPILIB
|
||||
SPI.transfer(*data);
|
||||
data++;
|
||||
#else
|
||||
SPDR = *data;
|
||||
data++;
|
||||
waitspi();
|
||||
#endif
|
||||
}
|
||||
CSPASSIVE;
|
||||
}
|
||||
@@ -583,6 +503,19 @@ Enc28J60Network::phyWrite(uint8_t address, uint16_t data)
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
Enc28J60Network::phyRead(uint8_t address)
|
||||
{
|
||||
writeReg(MIREGADR,address);
|
||||
writeReg(MICMD, MICMD_MIIRD);
|
||||
// wait until the PHY read completes
|
||||
while(readReg(MISTAT) & MISTAT_BUSY){
|
||||
delayMicroseconds(15);
|
||||
} //and MIRDH
|
||||
writeReg(MICMD, 0);
|
||||
return (readReg(MIRDL) | readReg(MIRDH) << 8);
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::clkout(uint8_t clk)
|
||||
{
|
||||
@@ -604,40 +537,27 @@ Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t
|
||||
len = setReadPtr(handle, pos, len)-1;
|
||||
CSACTIVE;
|
||||
// issue read command
|
||||
#if ENC28J60_USE_SPILIB
|
||||
SPI.transfer(ENC28J60_READ_BUF_MEM);
|
||||
#else
|
||||
SPDR = ENC28J60_READ_BUF_MEM;
|
||||
waitspi();
|
||||
#endif
|
||||
uint16_t i;
|
||||
for (i = 0; i < len; i+=2)
|
||||
{
|
||||
// read data
|
||||
#if ENC28J60_USE_SPILIB
|
||||
t = SPI.transfer(0x00) << 8;
|
||||
t += SPI.transfer(0x00);
|
||||
#else
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
t = SPDR << 8;
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
t += SPDR;
|
||||
#endif
|
||||
sum += t;
|
||||
if(sum < t) {
|
||||
sum++; /* carry */
|
||||
}
|
||||
}
|
||||
if(i == len) {
|
||||
#if ENC28J60_USE_SPILIB
|
||||
t = (SPI.transfer(0x00) << 8) + 0;
|
||||
#else
|
||||
SPDR = 0x00;
|
||||
waitspi();
|
||||
t = (SPDR << 8) + 0;
|
||||
#endif
|
||||
sum += t;
|
||||
if(sum < t) {
|
||||
sum++; /* carry */
|
||||
@@ -648,3 +568,30 @@ Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t
|
||||
/* Return sum in host byte order. */
|
||||
return sum;
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::powerOff()
|
||||
{
|
||||
writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN);
|
||||
delay(50);
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS);
|
||||
delay(50);
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV);
|
||||
}
|
||||
|
||||
void
|
||||
Enc28J60Network::powerOn()
|
||||
{
|
||||
writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV);
|
||||
delay(50);
|
||||
writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
|
||||
delay(50);
|
||||
}
|
||||
|
||||
bool
|
||||
Enc28J60Network::linkStatus()
|
||||
{
|
||||
return (phyRead(PHSTAT2) & 0x0400) > 0;
|
||||
}
|
||||
|
||||
Enc28J60Network Enc28J60;
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Enc28J60NetworkClass.h
|
||||
UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface.
|
||||
|
||||
Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
All rights reserved.
|
||||
|
||||
inspired by enc28j60.c file from the AVRlib library by Pascal Stang.
|
||||
For AVRlib See http://www.procyonengineering.com/
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef Enc28J60Network_H_
|
||||
#define Enc28J60Network_H_
|
||||
|
||||
#include "mempool.h"
|
||||
|
||||
#define ENC28J60_CONTROL_CS SS
|
||||
#define SPI_MOSI MOSI
|
||||
#define SPI_MISO MISO
|
||||
#define SPI_SCK SCK
|
||||
#define SPI_SS SS
|
||||
|
||||
#define UIP_RECEIVEBUFFERHANDLE 0xff
|
||||
|
||||
//#define ENC28J60DEBUG
|
||||
|
||||
/*
|
||||
* Empfangen von ip-header, arp etc...
|
||||
* wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection
|
||||
*/
|
||||
|
||||
class Enc28J60Network : public MemoryPool
|
||||
{
|
||||
|
||||
private:
|
||||
static uint16_t nextPacketPtr;
|
||||
static uint8_t bank;
|
||||
|
||||
static struct memblock receivePkt;
|
||||
|
||||
static uint8_t readOp(uint8_t op, uint8_t address);
|
||||
static void writeOp(uint8_t op, uint8_t address, uint8_t data);
|
||||
static uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len);
|
||||
static void setERXRDPT();
|
||||
static void readBuffer(uint16_t len, uint8_t* data);
|
||||
static void writeBuffer(uint16_t len, uint8_t* data);
|
||||
static uint8_t readByte(uint16_t addr);
|
||||
static void writeByte(uint16_t addr, uint8_t data);
|
||||
static void setBank(uint8_t address);
|
||||
static uint8_t readReg(uint8_t address);
|
||||
static void writeReg(uint8_t address, uint8_t data);
|
||||
static void writeRegPair(uint8_t address, uint16_t data);
|
||||
static void phyWrite(uint8_t address, uint16_t data);
|
||||
static uint16_t phyRead(uint8_t address);
|
||||
static void clkout(uint8_t clk);
|
||||
|
||||
friend void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress);
|
||||
|
||||
public:
|
||||
|
||||
uint8_t getrev(void);
|
||||
void powerOn();
|
||||
void powerOff();
|
||||
bool linkStatus();
|
||||
|
||||
static void init(uint8_t* macaddr);
|
||||
static memhandle receivePacket();
|
||||
static void freePacket();
|
||||
static memaddress blockSize(memhandle handle);
|
||||
static void sendPacket(memhandle handle);
|
||||
static uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len);
|
||||
static uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len);
|
||||
static void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len);
|
||||
static uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len);
|
||||
};
|
||||
|
||||
extern Enc28J60Network Enc28J60;
|
||||
#endif /* Enc28J60NetworkClass_H_ */
|
||||
+13
-9
@@ -22,13 +22,15 @@
|
||||
|
||||
#define POOLOFFSET 1
|
||||
|
||||
MemoryPool::MemoryPool(memaddress start, memaddress size)
|
||||
struct memblock MemoryPool::blocks[MEMPOOL_NUM_MEMBLOCKS+1];
|
||||
|
||||
void
|
||||
MemoryPool::init()
|
||||
{
|
||||
memset(&blocks[0], 0, sizeof(blocks));
|
||||
blocks[POOLSTART].begin = start;
|
||||
blocks[POOLSTART].begin = MEMPOOL_STARTADDRESS;
|
||||
blocks[POOLSTART].size = 0;
|
||||
blocks[POOLSTART].nextblock = NOBLOCK;
|
||||
poolsize = size;
|
||||
}
|
||||
|
||||
memhandle
|
||||
@@ -37,12 +39,12 @@ MemoryPool::allocBlock(memaddress size)
|
||||
memblock* best = NULL;
|
||||
memhandle cur = POOLSTART;
|
||||
memblock* block = &blocks[POOLSTART];
|
||||
memaddress bestsize = poolsize + 1;
|
||||
memaddress bestsize = MEMPOOL_SIZE + 1;
|
||||
|
||||
do
|
||||
{
|
||||
memhandle next = block->nextblock;
|
||||
memaddress freesize = ( next == NOBLOCK ? blocks[POOLSTART].begin + poolsize : blocks[next].begin) - block->begin - block->size;
|
||||
memaddress freesize = ( next == NOBLOCK ? blocks[POOLSTART].begin + MEMPOOL_SIZE : blocks[next].begin) - block->begin - block->size;
|
||||
if (freesize == size)
|
||||
{
|
||||
best = &blocks[cur];
|
||||
@@ -77,14 +79,14 @@ MemoryPool::allocBlock(memaddress size)
|
||||
memaddress* src = &nextblock->begin;
|
||||
if (dest != *src)
|
||||
{
|
||||
#ifdef MEMBLOCK_MV
|
||||
memblock_mv_cb(dest,*src,nextblock->size);
|
||||
#ifdef MEMPOOL_MEMBLOCK_MV
|
||||
MEMPOOL_MEMBLOCK_MV(dest,*src,nextblock->size);
|
||||
#endif
|
||||
*src = dest;
|
||||
}
|
||||
block = nextblock;
|
||||
}
|
||||
if (blocks[POOLSTART].begin + poolsize - block->begin - block->size >= size)
|
||||
if (blocks[POOLSTART].begin + MEMPOOL_SIZE - block->begin - block->size >= size)
|
||||
best = block;
|
||||
else
|
||||
goto notfound;
|
||||
@@ -93,7 +95,7 @@ MemoryPool::allocBlock(memaddress size)
|
||||
found:
|
||||
{
|
||||
block = &blocks[POOLOFFSET];
|
||||
for (cur = POOLOFFSET; cur < NUM_MEMBLOCKS + POOLOFFSET; cur++)
|
||||
for (cur = POOLOFFSET; cur < MEMPOOL_NUM_MEMBLOCKS + POOLOFFSET; cur++)
|
||||
{
|
||||
if (block->size)
|
||||
{
|
||||
@@ -118,6 +120,8 @@ MemoryPool::allocBlock(memaddress size)
|
||||
void
|
||||
MemoryPool::freeBlock(memhandle handle)
|
||||
{
|
||||
if (handle == NOBLOCK)
|
||||
return;
|
||||
memblock *b = &blocks[POOLSTART];
|
||||
|
||||
do
|
||||
+7
-24
@@ -27,18 +27,6 @@
|
||||
|
||||
#include "mempool_conf.h"
|
||||
|
||||
//#ifdef MEMBLOCK_MV
|
||||
//#define memblock_mv_cb(dest,src,size) MEMBLOCK_MV(dest,src,size)
|
||||
//#endif
|
||||
|
||||
#ifdef MEMBLOCK_ALLOC
|
||||
#define memblock_alloc_cb(address,size) MEMBLOCK_ALLOC(address,size)
|
||||
#endif
|
||||
|
||||
#ifdef MEMBLOCK_FREE
|
||||
#define memblock_free_cb(address,size) MEMBLOCK_FREE(address,size)
|
||||
#endif
|
||||
|
||||
struct memblock
|
||||
{
|
||||
memaddress begin;
|
||||
@@ -53,19 +41,14 @@ class MemoryPool
|
||||
#endif
|
||||
|
||||
protected:
|
||||
memaddress poolsize;
|
||||
struct memblock blocks[NUM_MEMBLOCKS+1];
|
||||
#ifdef MEMBLOCK_MV
|
||||
virtual void memblock_mv_cb(memaddress dest, memaddress src, memaddress size) = 0;
|
||||
#endif
|
||||
static struct memblock blocks[MEMPOOL_NUM_MEMBLOCKS+1];
|
||||
|
||||
public:
|
||||
MemoryPool(memaddress start, memaddress size);
|
||||
memhandle
|
||||
allocBlock(memaddress);
|
||||
void freeBlock(memhandle);
|
||||
void resizeBlock(memhandle handle, memaddress position);
|
||||
void resizeBlock(memhandle handle, memaddress position, memaddress size);
|
||||
memaddress blockSize(memhandle);
|
||||
static void init();
|
||||
static memhandle allocBlock(memaddress);
|
||||
static void freeBlock(memhandle);
|
||||
static void resizeBlock(memhandle handle, memaddress position);
|
||||
static void resizeBlock(memhandle handle, memaddress position, memaddress size);
|
||||
static memaddress blockSize(memhandle);
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef MEMPOOLCONF_H
|
||||
#define MEMPOOLCONF_H
|
||||
#include "uipethernet-conf.h"
|
||||
extern "C" {
|
||||
#include "uipopt.h"
|
||||
#include "enc28j60.h"
|
||||
}
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef uint16_t memaddress;
|
||||
typedef uint8_t memhandle;
|
||||
|
||||
#if UIP_SOCKET_NUMPACKETS and UIP_CONNS
|
||||
#define NUM_TCP_MEMBLOCKS (UIP_SOCKET_NUMPACKETS*2)*UIP_CONNS
|
||||
#else
|
||||
#define NUM_TCP_MEMBLOCKS 0
|
||||
#endif
|
||||
|
||||
#if UIP_UDP and UIP_UDP_CONNS
|
||||
#define NUM_UDP_MEMBLOCKS 3*UIP_UDP_CONNS
|
||||
#else
|
||||
#define NUM_UDP_MEMBLOCKS 0
|
||||
#endif
|
||||
|
||||
#define MEMPOOL_NUM_MEMBLOCKS (NUM_TCP_MEMBLOCKS+NUM_UDP_MEMBLOCKS)
|
||||
|
||||
#define MEMPOOL_STARTADDRESS TXSTART_INIT+1
|
||||
#define MEMPOOL_SIZE TXSTOP_INIT-TXSTART_INIT
|
||||
|
||||
void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress);
|
||||
|
||||
#define MEMPOOL_MEMBLOCK_MV(dest,src,size) enc28J60_mempool_block_move_callback(dest,src,size)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef UIPETHERNET_CONF_H
|
||||
#define UIPETHERNET_CONF_H
|
||||
|
||||
/* for TCP */
|
||||
#define UIP_SOCKET_NUMPACKETS 5
|
||||
#define UIP_CONF_MAX_CONNECTIONS 4
|
||||
|
||||
/* for UDP */
|
||||
#define UIP_CONF_UDP 0
|
||||
#define UIP_CONF_BROADCAST 1
|
||||
#define UIP_CONF_UDP_CONNS 4
|
||||
|
||||
/* number of attempts on write before returning number of bytes sent so far
|
||||
* set to -1 to block until connection is closed by timeout */
|
||||
#define UIP_ATTEMPTS_ON_WRITE -1
|
||||
|
||||
/* timeout after which UIPClient::connect gives up. The timeout is specified in seconds.
|
||||
* if set to a number <= 0 connect will timeout when uIP does (which might be longer than you expect...) */
|
||||
#define UIP_CONNECT_TIMEOUT -1
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user