Upgrade UIP-library to latest. Recommend Arduino IDE 1.5.7 when compiling EtherentGateway sketch.

This commit is contained in:
Henrik Ekblad
2014-09-16 22:17:07 +02:00
parent 27885fad9b
commit 26129b06a9
51 changed files with 594 additions and 3805 deletions
@@ -14,11 +14,15 @@
*
* The GW code is designed for Arduino 328p / 16MHz. ATmega168 does not have enough memory to run this program.
*
* COMPILING
* You must make sure to disable DEBUG in Sensor.h before compiling this sketch. Othervise the sketch won't fit in program space when downloading.
* For UIPEthernet(ENC28J60) usage: Note that I had to disable UDP and DHCP support in uipethernet-conf.h to reduce space. (which meas you ave to choose a static IP)
* For WizNET usage: Do *not* install the provided UIPEthernet-library. Remove UIPEthernet-include below and uncomment the Ethernet.h.
* COMPILING ENC28J60
* > Use Arduino IDE 1.5.7 (or later)
* > Disable DEBUG in Sensor.h before compiling this sketch. Othervise the sketch will probably not fit in program space when downloading.
* > Remove Ethernet.h include below and inlcude UIPEthernet.h
* COMPILING WizNET (W5100)
* > Remove UIPEthernet include below and include Ethernet.h.
*
* Note that I had to disable UDP and DHCP support in uipethernet-conf.h to reduce space. (which meas you ave to choose a static IP for that module)
* VERA CONFIGURATION:
* Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin.
* E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003
@@ -50,10 +54,10 @@
#include <stdarg.h>
// Use this if you have attached a Ethernet ENC28J60 shields
//#include <UIPEthernet.h>
#include <UIPEthernet.h>
// Use this fo WizNET module and Arduino Ethernet Shield
#include <Ethernet.h>
//#include <Ethernet.h>
#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled
@@ -66,7 +70,7 @@
#define RADIO_TX_LED_PIN 9 // the PCB, on board LED
#define IP_PORT 5003 // The port you want to open
IPAddress myIp (192, 168, 178, 66); // Configure your static ip-address here
IPAddress myIp (192, 168, 178, 66); // Configure your static ip-address here COMPILE ERROR HERE? Use Arduino IDE 1.5.7 or later!
// The MAC address can be anything you want but should be unique on your network.
// Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use.
+4 -2
View File
@@ -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
View File
@@ -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
+11 -6
View File
@@ -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
+60 -37
View File
@@ -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)
{
+23 -21
View File
@@ -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 */
+3 -3
View File
@@ -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)
+1 -1
View File
@@ -23,7 +23,7 @@
#import "Server.h"
#import "UIPClient.h"
class UIPServer : Server {
class UIPServer : public Server {
public:
UIPServer(uint16_t);
+81 -122
View File
@@ -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
+13 -13
View File
@@ -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
+1 -1
View File
@@ -4,6 +4,6 @@
#define Ethernet UIPEthernet
#define EthernetClient UIPClient
#define EthernetServer UIPServer
//#define EthernetUDP UIPUDP
#define EthernetUDP UIPUDP
#endif
-478
View File
@@ -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);
}
-178
View File
@@ -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
-422
View File
@@ -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;
}
-41
View File
@@ -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
-533
View File
@@ -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;
}
}
-104
View File
@@ -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
-433
View File
@@ -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
-125
View File
@@ -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
-63
View File
@@ -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;
}
-40
View File
@@ -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
-424
View File
@@ -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
-126
View File
@@ -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
@@ -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_ */
@@ -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
@@ -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