mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-16 11:21:18 +03:00
Merge branch 'dhcp' of github.com:amcewen/Arduino.
This includes DCHP support and new UDP API for the Ethernet library.
This commit is contained in:
@ -16,7 +16,7 @@ uint16_t Client::_srcport = 1024;
|
|||||||
Client::Client(uint8_t sock) : _sock(sock) {
|
Client::Client(uint8_t sock) : _sock(sock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::Client(uint8_t *ip, uint16_t port) : _ip(ip), _port(port), _sock(MAX_SOCK_NUM) {
|
Client::Client(IPAddress& ip, uint16_t port) : _ip(ip), _port(port), _sock(MAX_SOCK_NUM) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Client::connect() {
|
uint8_t Client::connect() {
|
||||||
@ -38,7 +38,7 @@ uint8_t Client::connect() {
|
|||||||
if (_srcport == 0) _srcport = 1024;
|
if (_srcport == 0) _srcport = 1024;
|
||||||
socket(_sock, SnMR::TCP, _srcport, 0);
|
socket(_sock, SnMR::TCP, _srcport, 0);
|
||||||
|
|
||||||
if (!::connect(_sock, _ip, _port)) {
|
if (!::connect(_sock, _ip.raw_address(), _port)) {
|
||||||
_sock = MAX_SOCK_NUM;
|
_sock = MAX_SOCK_NUM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ class Client : public Stream {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Client();
|
Client();
|
||||||
Client(uint8_t);
|
Client(uint8_t sock);
|
||||||
Client(uint8_t *, uint16_t);
|
Client(IPAddress& ip, uint16_t port);
|
||||||
|
|
||||||
uint8_t status();
|
uint8_t status();
|
||||||
uint8_t connect();
|
uint8_t connect();
|
||||||
@ -29,7 +29,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
static uint16_t _srcport;
|
static uint16_t _srcport;
|
||||||
uint8_t _sock;
|
uint8_t _sock;
|
||||||
uint8_t *_ip;
|
IPAddress _ip;
|
||||||
uint16_t _port;
|
uint16_t _port;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
341
libraries/Ethernet/Dhcp.cpp
Executable file
341
libraries/Ethernet/Dhcp.cpp
Executable file
@ -0,0 +1,341 @@
|
|||||||
|
// DHCP Library v0.3 - April 25, 2009
|
||||||
|
// Author: Jordan Terrell - blog.jordanterrell.com
|
||||||
|
|
||||||
|
#include "w5100.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "Dhcp.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
|
||||||
|
{
|
||||||
|
uint8_t dhcp_state = STATE_DHCP_START;
|
||||||
|
uint8_t messageType = 0;
|
||||||
|
|
||||||
|
// zero out _dhcpMacAddr, _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
|
||||||
|
memset(_dhcpMacAddr, 0, 26);
|
||||||
|
|
||||||
|
memcpy((void*)_dhcpMacAddr, (void*)mac, 6);
|
||||||
|
|
||||||
|
// Pick an initial transaction ID
|
||||||
|
_dhcpTransactionId = random(1UL, 2000UL);
|
||||||
|
_dhcpInitialTransactionId = _dhcpTransactionId;
|
||||||
|
|
||||||
|
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_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;
|
||||||
|
}
|
||||||
|
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) + 3; // length of hostname + last 3 bytes of mac address
|
||||||
|
strcpy((char*)&(buffer[18]), HOST_NAME);
|
||||||
|
|
||||||
|
buffer[24] = _dhcpMacAddr[3];
|
||||||
|
buffer[25] = _dhcpMacAddr[4];
|
||||||
|
buffer[26] = _dhcpMacAddr[5];
|
||||||
|
|
||||||
|
//put data in W5100 transmit buffer
|
||||||
|
_dhcpUdpSocket.write(buffer, 27);
|
||||||
|
|
||||||
|
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 - 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);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case dns :
|
||||||
|
opt_len = _dhcpUdpSocket.read();
|
||||||
|
_dhcpUdpSocket.read(_dhcpDnsServerIp, 4);
|
||||||
|
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 dhcpIPaddrLeaseTime :
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
158
libraries/Ethernet/Dhcp.h
Executable file
158
libraries/Ethernet/Dhcp.h
Executable file
@ -0,0 +1,158 @@
|
|||||||
|
// DHCP Library v0.3 - April 25, 2009
|
||||||
|
// Author: Jordan Terrell - blog.jordanterrell.com
|
||||||
|
|
||||||
|
#ifndef Dhcp_h
|
||||||
|
#define Dhcp_h
|
||||||
|
|
||||||
|
#include "Udp.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 "WIZnet"
|
||||||
|
|
||||||
|
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];
|
||||||
|
UDP _dhcpUdpSocket;
|
||||||
|
|
||||||
|
void presend_DHCP();
|
||||||
|
void send_DHCP_MESSAGE(uint8_t, uint16_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);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,6 @@
|
|||||||
#include "w5100.h"
|
#include "w5100.h"
|
||||||
#include "Ethernet.h"
|
#include "Ethernet.h"
|
||||||
|
#include "Dhcp.h"
|
||||||
|
|
||||||
// XXX: don't make assumptions about the value of MAX_SOCK_NUM.
|
// XXX: don't make assumptions about the value of MAX_SOCK_NUM.
|
||||||
uint8_t EthernetClass::_state[MAX_SOCK_NUM] = {
|
uint8_t EthernetClass::_state[MAX_SOCK_NUM] = {
|
||||||
@ -7,30 +8,78 @@ uint8_t EthernetClass::_state[MAX_SOCK_NUM] = {
|
|||||||
uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = {
|
uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = {
|
||||||
0, 0, 0, 0 };
|
0, 0, 0, 0 };
|
||||||
|
|
||||||
void EthernetClass::begin(uint8_t *mac, uint8_t *ip)
|
int EthernetClass::begin(uint8_t *mac_address)
|
||||||
{
|
{
|
||||||
uint8_t gateway[4];
|
DhcpClass dhcp;
|
||||||
gateway[0] = ip[0];
|
|
||||||
gateway[1] = ip[1];
|
// Initialise the basic info
|
||||||
gateway[2] = ip[2];
|
W5100.init();
|
||||||
|
W5100.setMACAddress(mac_address);
|
||||||
|
W5100.setIPAddress(IPAddress(0,0,0,0).raw_address());
|
||||||
|
|
||||||
|
// Now try to get our config info from a DHCP server
|
||||||
|
int ret = dhcp.beginWithDHCP(mac_address);
|
||||||
|
if(ret == 1)
|
||||||
|
{
|
||||||
|
// We've successfully found a DHCP server and got our configuration info, so set things
|
||||||
|
// accordingly
|
||||||
|
W5100.setIPAddress(dhcp.getLocalIp().raw_address());
|
||||||
|
W5100.setGatewayIp(dhcp.getGatewayIp().raw_address());
|
||||||
|
W5100.setSubnetMask(dhcp.getSubnetMask().raw_address());
|
||||||
|
_dnsServerAddress = dhcp.getDnsServerIp();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip)
|
||||||
|
{
|
||||||
|
// Assume the gateway will be the machine on the same network as the local IP
|
||||||
|
// but with last octet being '1'
|
||||||
|
IPAddress gateway = local_ip;
|
||||||
gateway[3] = 1;
|
gateway[3] = 1;
|
||||||
begin(mac, ip, gateway);
|
begin(mac_address, local_ip, gateway);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EthernetClass::begin(uint8_t *mac, uint8_t *ip, uint8_t *gateway)
|
void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress gateway)
|
||||||
{
|
{
|
||||||
uint8_t subnet[] = {
|
IPAddress subnet(255, 255, 255, 0);
|
||||||
255, 255, 255, 0 };
|
begin(mac_address, local_ip, gateway, subnet);
|
||||||
begin(mac, ip, gateway, subnet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EthernetClass::begin(uint8_t *mac, uint8_t *ip, uint8_t *gateway, uint8_t *subnet)
|
void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress gateway, IPAddress subnet)
|
||||||
{
|
{
|
||||||
W5100.init();
|
W5100.init();
|
||||||
W5100.setMACAddress(mac);
|
W5100.setMACAddress(mac);
|
||||||
W5100.setIPAddress(ip);
|
W5100.setIPAddress(local_ip._address);
|
||||||
W5100.setGatewayIp(gateway);
|
W5100.setGatewayIp(gateway._address);
|
||||||
W5100.setSubnetMask(subnet);
|
W5100.setSubnetMask(subnet._address);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress EthernetClass::localIP()
|
||||||
|
{
|
||||||
|
IPAddress ret;
|
||||||
|
W5100.getIPAddress(ret.raw_address());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress EthernetClass::subnetMask()
|
||||||
|
{
|
||||||
|
IPAddress ret;
|
||||||
|
W5100.getSubnetMask(ret.raw_address());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress EthernetClass::gatewayIP()
|
||||||
|
{
|
||||||
|
IPAddress ret;
|
||||||
|
W5100.getGatewayIp(ret.raw_address());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress EthernetClass::dnsServerIP()
|
||||||
|
{
|
||||||
|
return _dnsServerAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
EthernetClass Ethernet;
|
EthernetClass Ethernet;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
//#include "w5100.h"
|
//#include "w5100.h"
|
||||||
|
#include "IPAddress.h"
|
||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
#include "Server.h"
|
#include "Server.h"
|
||||||
|
|
||||||
@ -10,12 +11,23 @@
|
|||||||
|
|
||||||
class EthernetClass {
|
class EthernetClass {
|
||||||
private:
|
private:
|
||||||
|
IPAddress _dnsServerAddress;
|
||||||
public:
|
public:
|
||||||
static uint8_t _state[MAX_SOCK_NUM];
|
static uint8_t _state[MAX_SOCK_NUM];
|
||||||
static uint16_t _server_port[MAX_SOCK_NUM];
|
static uint16_t _server_port[MAX_SOCK_NUM];
|
||||||
void begin(uint8_t *, uint8_t *);
|
// Initialise the Ethernet shield to use the provided MAC address and gain the rest of the
|
||||||
void begin(uint8_t *, uint8_t *, uint8_t *);
|
// configuration through DHCP.
|
||||||
void begin(uint8_t *, uint8_t *, uint8_t *, uint8_t *);
|
// Returns 0 if the DHCP configuration failed, and 1 if it succeeded
|
||||||
|
int begin(uint8_t *mac_address);
|
||||||
|
void begin(uint8_t *mac_address, IPAddress local_ip);
|
||||||
|
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress gateway);
|
||||||
|
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress gateway, IPAddress subnet);
|
||||||
|
|
||||||
|
IPAddress localIP();
|
||||||
|
IPAddress subnetMask();
|
||||||
|
IPAddress gatewayIP();
|
||||||
|
IPAddress dnsServerIP();
|
||||||
|
|
||||||
friend class Client;
|
friend class Client;
|
||||||
friend class Server;
|
friend class Server;
|
||||||
};
|
};
|
||||||
|
44
libraries/Ethernet/IPAddress.cpp
Normal file
44
libraries/Ethernet/IPAddress.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <IPAddress.h>
|
||||||
|
|
||||||
|
IPAddress::IPAddress()
|
||||||
|
{
|
||||||
|
memset(_address, 0, sizeof(_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
|
||||||
|
{
|
||||||
|
_address[0] = first_octet;
|
||||||
|
_address[1] = second_octet;
|
||||||
|
_address[2] = third_octet;
|
||||||
|
_address[3] = fourth_octet;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress::IPAddress(uint32_t address)
|
||||||
|
{
|
||||||
|
memcpy(_address, &address, sizeof(_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress::IPAddress(const uint8_t *address)
|
||||||
|
{
|
||||||
|
memcpy(_address, address, sizeof(_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress& IPAddress::operator=(const uint8_t *address)
|
||||||
|
{
|
||||||
|
memcpy(_address, address, sizeof(_address));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress& IPAddress::operator=(uint32_t address)
|
||||||
|
{
|
||||||
|
memcpy(_address, (const uint8_t *)&address, sizeof(_address));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPAddress::operator==(const uint8_t* addr)
|
||||||
|
{
|
||||||
|
return memcmp(addr, _address, sizeof(_address)) == 0;
|
||||||
|
}
|
||||||
|
|
68
libraries/Ethernet/IPAddress.h
Normal file
68
libraries/Ethernet/IPAddress.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* MIT License:
|
||||||
|
* Copyright (c) 2011 Adrian McEwen
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* adrianm@mcqn.com 1/1/2011
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IPAddress_h
|
||||||
|
#define IPAddress_h
|
||||||
|
|
||||||
|
// A class to make it easier to handle and pass around IP addresses
|
||||||
|
|
||||||
|
class IPAddress {
|
||||||
|
private:
|
||||||
|
uint8_t _address[4]; // IPv4 address
|
||||||
|
// Access the raw byte array containing the address. Because this returns a pointer
|
||||||
|
// to the internal structure rather than a copy of the address this function should only
|
||||||
|
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||||
|
// stored.
|
||||||
|
uint8_t* raw_address() { return _address; };
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructors
|
||||||
|
IPAddress();
|
||||||
|
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||||
|
IPAddress(uint32_t address);
|
||||||
|
IPAddress(const uint8_t *address);
|
||||||
|
|
||||||
|
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||||
|
// to a four-byte uint8_t array is expected
|
||||||
|
operator uint32_t() { return *((uint32_t*)_address); };
|
||||||
|
bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); };
|
||||||
|
bool operator==(const uint8_t* addr);
|
||||||
|
|
||||||
|
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||||
|
uint8_t operator[](int index) const { return _address[index]; };
|
||||||
|
uint8_t& operator[](int index) { return _address[index]; };
|
||||||
|
|
||||||
|
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
||||||
|
IPAddress& operator=(const uint8_t *address);
|
||||||
|
IPAddress& operator=(uint32_t address);
|
||||||
|
|
||||||
|
friend class EthernetClass;
|
||||||
|
friend class UDP;
|
||||||
|
friend class Client;
|
||||||
|
friend class Server;
|
||||||
|
friend class DhcpClass;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -56,97 +56,12 @@ uint8_t UDP::begin(uint16_t port) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send packet contained in buf of length len to peer at specified ip, and port */
|
|
||||||
/* Use this function to transmit binary data that might contain 0x00 bytes*/
|
|
||||||
/* This function returns sent data size for success else -1. */
|
|
||||||
uint16_t UDP::sendPacket(uint8_t * buf, uint16_t len, uint8_t * ip, uint16_t port){
|
|
||||||
return sendto(_sock,(const uint8_t *)buf,len,ip,port);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send zero-terminated string str as packet to peer at specified ip, and port */
|
|
||||||
/* This function returns sent data size for success else -1. */
|
|
||||||
uint16_t UDP::sendPacket(const char str[], uint8_t * ip, uint16_t port){
|
|
||||||
// compute strlen
|
|
||||||
const char *s;
|
|
||||||
for(s = str; *s; ++s);
|
|
||||||
uint16_t len = (s-str);
|
|
||||||
// send packet
|
|
||||||
return sendto(_sock,(const uint8_t *)str,len,ip,port);
|
|
||||||
}
|
|
||||||
/* Is data available in rx buffer? Returns 0 if no, number of available bytes if yes.
|
/* Is data available in rx buffer? Returns 0 if no, number of available bytes if yes.
|
||||||
* returned value includes 8 byte UDP header!*/
|
* returned value includes 8 byte UDP header!*/
|
||||||
int UDP::available() {
|
int UDP::available() {
|
||||||
return W5100.getRXReceivedSize(_sock);
|
return W5100.getRXReceivedSize(_sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read a received packet into buffer buf (which is of maximum length len); */
|
|
||||||
/* store calling ip and port as well. Call available() to make sure data is ready first. */
|
|
||||||
/* NOTE: I don't believe len is ever checked in implementation of recvfrom(),*/
|
|
||||||
/* so it's easy to overflow buffer. so we check and truncate. */
|
|
||||||
/* returns number of bytes read, or negative number of bytes we would have needed if we truncated */
|
|
||||||
int UDP::readPacket(uint8_t * buf, uint16_t bufLen, uint8_t *ip, uint16_t *port) {
|
|
||||||
int packetLen = available()-8; //skip UDP header;
|
|
||||||
if(packetLen < 0 ) return 0; // no real data here
|
|
||||||
if(packetLen > (int)bufLen) {
|
|
||||||
//packet is too large - truncate
|
|
||||||
//HACK - hand-parse the UDP packet using TCP recv method
|
|
||||||
uint8_t tmpBuf[8];
|
|
||||||
int i;
|
|
||||||
//read 8 header bytes and get IP and port from it
|
|
||||||
recv(_sock,tmpBuf,8);
|
|
||||||
ip[0] = tmpBuf[0];
|
|
||||||
ip[1] = tmpBuf[1];
|
|
||||||
ip[2] = tmpBuf[2];
|
|
||||||
ip[3] = tmpBuf[3];
|
|
||||||
*port = tmpBuf[4];
|
|
||||||
*port = (*port << 8) + tmpBuf[5];
|
|
||||||
|
|
||||||
//now copy first (bufLen) bytes into buf
|
|
||||||
for(i=0;i<(int)bufLen;i++) {
|
|
||||||
recv(_sock,tmpBuf,1);
|
|
||||||
buf[i]=tmpBuf[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
//and just read the rest byte by byte and throw it away
|
|
||||||
while(available()) {
|
|
||||||
recv(_sock,tmpBuf,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (-1*packetLen);
|
|
||||||
|
|
||||||
//ALTERNATIVE: requires stdlib - takes a bunch of space
|
|
||||||
/*//create new buffer and read everything into it
|
|
||||||
uint8_t * tmpBuf = (uint8_t *)malloc(packetLen);
|
|
||||||
recvfrom(_sock,tmpBuf,packetLen,ip,port);
|
|
||||||
if(!tmpBuf) return 0; //couldn't allocate
|
|
||||||
// copy first bufLen bytes
|
|
||||||
for(unsigned int i=0; i<bufLen; i++) {
|
|
||||||
buf[i]=tmpBuf[i];
|
|
||||||
}
|
|
||||||
//free temp buffer
|
|
||||||
free(tmpBuf);
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
return recvfrom(_sock,buf,bufLen,ip,port);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read a received packet, throw away peer's ip and port. See note above. */
|
|
||||||
int UDP::readPacket(uint8_t * buf, uint16_t len) {
|
|
||||||
uint8_t ip[4];
|
|
||||||
uint16_t port[1];
|
|
||||||
return recvfrom(_sock,buf,len,ip,port);
|
|
||||||
}
|
|
||||||
|
|
||||||
int UDP::readPacket(char * buf, uint16_t bufLen, uint8_t *ip, uint16_t &port) {
|
|
||||||
uint16_t myPort;
|
|
||||||
uint16_t ret = readPacket( (byte*)buf, bufLen, ip, &myPort);
|
|
||||||
port = myPort;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release any resources being used by this UDP instance */
|
/* Release any resources being used by this UDP instance */
|
||||||
void UDP::stop()
|
void UDP::stop()
|
||||||
{
|
{
|
||||||
@ -159,3 +74,93 @@ void UDP::stop()
|
|||||||
_sock = MAX_SOCK_NUM;
|
_sock = MAX_SOCK_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int UDP::beginPacket(IPAddress ip, uint16_t port)
|
||||||
|
{
|
||||||
|
_offset = 0;
|
||||||
|
return startUDP(_sock, ip.raw_address(), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDP::endPacket()
|
||||||
|
{
|
||||||
|
return sendUDP(_sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDP::write(uint8_t byte)
|
||||||
|
{
|
||||||
|
write(&byte, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDP::write(const char *str)
|
||||||
|
{
|
||||||
|
size_t len = strlen(str);
|
||||||
|
write((const uint8_t *)str, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDP::write(const uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
uint16_t bytes_written = bufferData(_sock, _offset, buffer, size);
|
||||||
|
_offset += bytes_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDP::parsePacket()
|
||||||
|
{
|
||||||
|
//HACK - hand-parse the UDP packet using TCP recv method
|
||||||
|
uint8_t tmpBuf[8];
|
||||||
|
int ret =0;
|
||||||
|
//read 8 header bytes and get IP and port from it
|
||||||
|
ret = recv(_sock,tmpBuf,8);
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
_remoteIP = tmpBuf;
|
||||||
|
_remotePort = tmpBuf[4];
|
||||||
|
_remotePort = (_remotePort << 8) + tmpBuf[5];
|
||||||
|
// When we get here, any remaining bytes are the data
|
||||||
|
ret = available();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDP::read()
|
||||||
|
{
|
||||||
|
uint8_t byte;
|
||||||
|
if (recv(_sock, &byte, 1) > 0)
|
||||||
|
{
|
||||||
|
// We read things without any problems
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
// If we get here, there's no data available
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDP::read(unsigned char* buffer, size_t len)
|
||||||
|
{
|
||||||
|
/* In the readPacket that copes with truncating packets, the buffer was
|
||||||
|
filled with this code. Not sure why it loops round reading out a byte
|
||||||
|
at a time.
|
||||||
|
int i;
|
||||||
|
for(i=0;i<(int)bufLen;i++) {
|
||||||
|
recv(_sock,tmpBuf,1);
|
||||||
|
buf[i]=tmpBuf[0];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return recv(_sock, buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDP::peek()
|
||||||
|
{
|
||||||
|
uint8_t b;
|
||||||
|
// Unlike recv, peek doesn't check to see if there's any data available, so we must
|
||||||
|
if (!available())
|
||||||
|
return -1;
|
||||||
|
::peek(_sock, &b);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDP::flush()
|
||||||
|
{
|
||||||
|
while (available())
|
||||||
|
{
|
||||||
|
read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -37,28 +37,60 @@
|
|||||||
#ifndef udp_h
|
#ifndef udp_h
|
||||||
#define udp_h
|
#define udp_h
|
||||||
|
|
||||||
|
#include <Stream.h>
|
||||||
|
#include <IPAddress.h>
|
||||||
|
|
||||||
#define UDP_TX_PACKET_MAX_SIZE 24
|
#define UDP_TX_PACKET_MAX_SIZE 24
|
||||||
|
|
||||||
class UDP {
|
class UDP : public Stream {
|
||||||
private:
|
private:
|
||||||
uint8_t _sock; // socket ID for Wiz5100
|
uint8_t _sock; // socket ID for Wiz5100
|
||||||
uint16_t _port; // local port to listen on
|
uint16_t _port; // local port to listen on
|
||||||
|
IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed
|
||||||
|
uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed
|
||||||
|
uint16_t _offset; // offset into the packet being sent
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UDP();
|
UDP(); // 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
|
uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||||
int available(); // has data been received?
|
void stop(); // Finish with the UDP socket
|
||||||
|
|
||||||
// C-style buffer-oriented functions
|
// Sending UDP packets
|
||||||
uint16_t sendPacket(uint8_t *, uint16_t, uint8_t *, uint16_t); //send a packet to specified peer
|
|
||||||
uint16_t sendPacket(const char[], uint8_t *, uint16_t); //send a string as a packet to specified peer
|
// Start building up a packet to send to the remote host specific in ip and port
|
||||||
int readPacket(uint8_t *, uint16_t); // read a received packet
|
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||||
int readPacket(uint8_t *, uint16_t, uint8_t *, uint16_t *); // read a received packet, also return sender's ip and port
|
int beginPacket(IPAddress ip, uint16_t port);
|
||||||
// readPacket that fills a character string buffer
|
// Finish off this packet and send it
|
||||||
int readPacket(char *, uint16_t, uint8_t *, uint16_t &);
|
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||||
|
int endPacket();
|
||||||
|
// Write a single byte into the packet
|
||||||
|
virtual void write(uint8_t);
|
||||||
|
// Write a string of characters into the packet
|
||||||
|
virtual void write(const char *str);
|
||||||
|
// Write size bytes from buffer into the packet
|
||||||
|
virtual void write(const uint8_t *buffer, size_t size);
|
||||||
|
|
||||||
// Finish with the UDP socket
|
// Start processing the next available incoming packet
|
||||||
void stop();
|
// 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
|
||||||
|
virtual int available();
|
||||||
|
// Read a single byte from the current packet
|
||||||
|
virtual 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
|
||||||
|
virtual 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
|
||||||
|
virtual 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
|
||||||
|
virtual int peek();
|
||||||
|
virtual void flush(); // Finish reading the current packet
|
||||||
|
|
||||||
|
// Return the IP address of the host who sent the current incoming packet
|
||||||
|
IPAddress remoteIP() { return _remoteIP; };
|
||||||
|
// Return the port of the host who sent the current incoming packet
|
||||||
|
uint16_t remotePort() { return _remotePort; };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,12 +31,9 @@
|
|||||||
byte mac[] = {
|
byte mac[] = {
|
||||||
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||||
// assign an IP address for the controller:
|
// assign an IP address for the controller:
|
||||||
byte ip[] = {
|
IPAddress ip(192,168,1,20);
|
||||||
192,168,1,20 };
|
IPAddress gateway(192,168,1,1);
|
||||||
byte gateway[] = {
|
IPAddress subnet(255, 255, 255, 0);
|
||||||
192,168,1,1};
|
|
||||||
byte subnet[] = {
|
|
||||||
255, 255, 255, 0 };
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize the Ethernet server library
|
// Initialize the Ethernet server library
|
||||||
|
@ -24,9 +24,9 @@
|
|||||||
// The IP address will be dependent on your local network.
|
// The IP address will be dependent on your local network.
|
||||||
// gateway and subnet are optional:
|
// gateway and subnet are optional:
|
||||||
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||||
byte ip[] = { 192,168,1, 177 };
|
IPAddress ip(192,168,1, 177);
|
||||||
byte gateway[] = { 192,168,1, 1 };
|
IPAddress gateway(192,168,1, 1);
|
||||||
byte subnet[] = { 255, 255, 0, 0 };
|
IPAddress subnet(255, 255, 0, 0);
|
||||||
|
|
||||||
// telnet defaults to port 23
|
// telnet defaults to port 23
|
||||||
Server server(23);
|
Server server(23);
|
||||||
@ -60,4 +60,4 @@ void loop() {
|
|||||||
// echo the bytes to the server as well:
|
// echo the bytes to the server as well:
|
||||||
Serial.print(thisChar);
|
Serial.print(thisChar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,20 +23,13 @@
|
|||||||
#include <Ethernet.h>
|
#include <Ethernet.h>
|
||||||
|
|
||||||
// assign a MAC address for the ethernet controller.
|
// assign a MAC address for the ethernet controller.
|
||||||
|
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
|
||||||
// fill in your address here:
|
// fill in your address here:
|
||||||
byte mac[] = {
|
byte mac[] = {
|
||||||
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||||
// assign an IP address for the controller:
|
|
||||||
byte ip[] = {
|
|
||||||
192,169,1,20 };
|
|
||||||
byte gateway[] = {
|
|
||||||
192,168,1,1};
|
|
||||||
byte subnet[] = {
|
|
||||||
255, 255, 255, 0 };
|
|
||||||
|
|
||||||
// The address of the server you want to connect to (pachube.com):
|
// The address of the server you want to connect to (pachube.com):
|
||||||
byte server[] = {
|
IPAddress server(209,40,205,190);
|
||||||
209,40,205,190 };
|
|
||||||
|
|
||||||
// initialize the library instance:
|
// initialize the library instance:
|
||||||
Client client(server, 80);
|
Client client(server, 80);
|
||||||
@ -46,9 +39,15 @@ boolean lastConnected = false; // state of the connection last time through
|
|||||||
const int postingInterval = 10000; //delay between updates to Pachube.com
|
const int postingInterval = 10000; //delay between updates to Pachube.com
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// start the ethernet connection and serial port:
|
// start serial port:
|
||||||
Ethernet.begin(mac, ip);
|
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
// start the Ethernet connection:
|
||||||
|
if (Ethernet.begin(mac) == 0) {
|
||||||
|
Serial.println("Failed to configure Ethernet using DHCP");
|
||||||
|
// no point in carrying on, so do nothing forevermore:
|
||||||
|
for(;;)
|
||||||
|
;
|
||||||
|
}
|
||||||
// give the ethernet module time to boot up:
|
// give the ethernet module time to boot up:
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,12 @@
|
|||||||
byte mac[] = {
|
byte mac[] = {
|
||||||
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||||
// assign an IP address for the controller:
|
// assign an IP address for the controller:
|
||||||
byte ip[] = {
|
IPAddress ip(192,169,1,20);
|
||||||
192,169,1,20 };
|
IPAddress gateway(192,168,1,1);
|
||||||
byte gateway[] = {
|
IPAddress subnet(255, 255, 255, 0);
|
||||||
192,168,1,1};
|
|
||||||
byte subnet[] = {
|
|
||||||
255, 255, 255, 0 };
|
|
||||||
|
|
||||||
// The address of the server you want to connect to (pachube.com):
|
// The address of the server you want to connect to (pachube.com):
|
||||||
byte server[] = {
|
IPAddress server(209,40,205,190);
|
||||||
209,40,205,190 };
|
|
||||||
|
|
||||||
// initialize the library instance:
|
// initialize the library instance:
|
||||||
Client client(server, 80);
|
Client client(server, 80);
|
||||||
|
@ -24,12 +24,10 @@
|
|||||||
// The IP address will be dependent on your local network:
|
// The IP address will be dependent on your local network:
|
||||||
byte mac[] = {
|
byte mac[] = {
|
||||||
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||||
byte ip[] = {
|
IPAddress ip(192,168,1,177);
|
||||||
192,168,1,177 };
|
|
||||||
|
|
||||||
// Enter the IP address of the server you're connecting to:
|
// Enter the IP address of the server you're connecting to:
|
||||||
byte server[] = {
|
IPAddress server(1,1,1,1);
|
||||||
1,1,1,1 };
|
|
||||||
|
|
||||||
// Initialize the Ethernet client library
|
// Initialize the Ethernet client library
|
||||||
// with the IP address and port of the server
|
// with the IP address and port of the server
|
||||||
|
@ -22,15 +22,10 @@
|
|||||||
// The IP address will be dependent on your local network:
|
// The IP address will be dependent on your local network:
|
||||||
byte mac[] = {
|
byte mac[] = {
|
||||||
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||||
byte ip[] = {
|
IPAddress ip(192, 168, 1, 177);
|
||||||
192,168,1,177 };
|
|
||||||
|
|
||||||
unsigned int localPort = 8888; // local port to listen on
|
unsigned int localPort = 8888; // local port to listen on
|
||||||
|
|
||||||
// the next two variables are set when a packet is received
|
|
||||||
byte remoteIp[4]; // holds received packet's originating IP
|
|
||||||
unsigned int remotePort; // holds received packet's originating port
|
|
||||||
|
|
||||||
// buffers for receiving and sending data
|
// buffers for receiving and sending data
|
||||||
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
|
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
|
||||||
char ReplyBuffer[] = "acknowledged"; // a string to send back
|
char ReplyBuffer[] = "acknowledged"; // a string to send back
|
||||||
@ -48,19 +43,33 @@ void setup() {
|
|||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// if there's data available, read a packet
|
// if there's data available, read a packet
|
||||||
int packetSize = Udp.available(); // note that this includes the UDP header
|
int packetSize = Udp.parsePacket();
|
||||||
if(packetSize)
|
if(packetSize)
|
||||||
{
|
{
|
||||||
packetSize = packetSize - 8; // subtract the 8 byte header
|
|
||||||
Serial.print("Received packet of size ");
|
Serial.print("Received packet of size ");
|
||||||
Serial.println(packetSize);
|
Serial.println(packetSize);
|
||||||
|
Serial.print("From ");
|
||||||
|
IPAddress remote = Udp.remoteIP();
|
||||||
|
for (int i =0; i < 4; i++)
|
||||||
|
{
|
||||||
|
Serial.print(remote[i], DEC);
|
||||||
|
if (i < 3)
|
||||||
|
{
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.print(", port ");
|
||||||
|
Serial.println(Udp.remotePort());
|
||||||
|
|
||||||
// read the packet into packetBufffer and get the senders IP addr and port number
|
// read the packet into packetBufffer
|
||||||
Udp.readPacket(packetBuffer,UDP_TX_PACKET_MAX_SIZE, remoteIp, remotePort);
|
Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
|
||||||
Serial.println("Contents:");
|
Serial.println("Contents:");
|
||||||
Serial.println(packetBuffer);
|
Serial.println(packetBuffer);
|
||||||
|
|
||||||
Udp.sendPacket( ReplyBuffer, remoteIp, remotePort);
|
// send a reply, to the IP address and port that sent us the packet we received
|
||||||
|
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
|
||||||
|
Udp.write(ReplyBuffer);
|
||||||
|
Udp.endPacket();
|
||||||
}
|
}
|
||||||
delay(10);
|
delay(10);
|
||||||
}
|
}
|
||||||
|
@ -20,18 +20,14 @@
|
|||||||
#include <Ethernet.h>
|
#include <Ethernet.h>
|
||||||
#include <Udp.h>
|
#include <Udp.h>
|
||||||
|
|
||||||
// Enter a MAC address and IP address for your controller below.
|
// Enter a MAC address for your controller below.
|
||||||
// The IP address will be dependent on your local network:
|
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
|
||||||
byte mac[] = {
|
byte mac[] = {
|
||||||
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||||
byte ip[] = {
|
|
||||||
192,168,1,177 };
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int localPort = 8888; // local port to listen for UDP packets
|
unsigned int localPort = 8888; // local port to listen for UDP packets
|
||||||
|
|
||||||
byte timeServer[] = {
|
IPAddress timeServer(192, 43, 244, 18); // time.nist.gov NTP server
|
||||||
192, 43, 244, 18}; // time.nist.gov NTP server
|
|
||||||
|
|
||||||
const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message
|
const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message
|
||||||
|
|
||||||
@ -42,11 +38,16 @@ UDP Udp;
|
|||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// start Ethernet and UDP
|
|
||||||
Ethernet.begin(mac,ip);
|
|
||||||
Udp.begin(localPort);
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// start Ethernet and UDP
|
||||||
|
if (Ethernet.begin(mac) == 0) {
|
||||||
|
Serial.println("Failed to configure Ethernet using DHCP");
|
||||||
|
// no point in carrying on, so do nothing forevermore:
|
||||||
|
for(;;)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
Udp.begin(localPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
@ -55,8 +56,9 @@ void loop()
|
|||||||
|
|
||||||
// wait to see if a reply is available
|
// wait to see if a reply is available
|
||||||
delay(1000);
|
delay(1000);
|
||||||
if ( Udp.available() ) {
|
if ( Udp.parsePacket() ) {
|
||||||
Udp.readPacket(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer
|
// We've received a packet, read the data from it
|
||||||
|
Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer
|
||||||
|
|
||||||
//the timestamp starts at byte 40 of the received packet and is four bytes,
|
//the timestamp starts at byte 40 of the received packet and is four bytes,
|
||||||
// or two words, long. First, esxtract the two words:
|
// or two words, long. First, esxtract the two words:
|
||||||
@ -100,7 +102,7 @@ void loop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send an NTP request to the time server at the given address
|
// send an NTP request to the time server at the given address
|
||||||
unsigned long sendNTPpacket(byte *address)
|
unsigned long sendNTPpacket(IPAddress& address)
|
||||||
{
|
{
|
||||||
// set all bytes in the buffer to 0
|
// set all bytes in the buffer to 0
|
||||||
memset(packetBuffer, 0, NTP_PACKET_SIZE);
|
memset(packetBuffer, 0, NTP_PACKET_SIZE);
|
||||||
@ -118,7 +120,9 @@ unsigned long sendNTPpacket(byte *address)
|
|||||||
|
|
||||||
// all NTP fields have been given values, now
|
// all NTP fields have been given values, now
|
||||||
// you can send a packet requesting a timestamp:
|
// you can send a packet requesting a timestamp:
|
||||||
Udp.sendPacket( packetBuffer,NTP_PACKET_SIZE, address, 123); //NTP requests are to port 123
|
Udp.beginPacket(address, 123); //NTP requests are to port 123
|
||||||
|
Udp.write(packetBuffer,NTP_PACKET_SIZE);
|
||||||
|
Udp.endPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,11 +15,10 @@
|
|||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <Ethernet.h>
|
#include <Ethernet.h>
|
||||||
|
|
||||||
// Enter a MAC address and IP address for your controller below.
|
// Enter a MAC address for your controller below.
|
||||||
// The IP address will be dependent on your local network:
|
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
|
||||||
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||||
byte ip[] = { 192,168,1,177 };
|
IPAddress server(173,194,33,104); // Google
|
||||||
byte server[] = { 173,194,33,104 }; // Google
|
|
||||||
|
|
||||||
// Initialize the Ethernet client library
|
// Initialize the Ethernet client library
|
||||||
// with the IP address and port of the server
|
// with the IP address and port of the server
|
||||||
@ -27,10 +26,15 @@ byte server[] = { 173,194,33,104 }; // Google
|
|||||||
Client client(server, 80);
|
Client client(server, 80);
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// start the Ethernet connection:
|
|
||||||
Ethernet.begin(mac, ip);
|
|
||||||
// start the serial library:
|
// start the serial library:
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
// start the Ethernet connection:
|
||||||
|
if (Ethernet.begin(mac) == 0) {
|
||||||
|
Serial.println("Failed to configure Ethernet using DHCP");
|
||||||
|
// no point in carrying on, so do nothing forevermore:
|
||||||
|
for(;;)
|
||||||
|
;
|
||||||
|
}
|
||||||
// give the Ethernet shield a second to initialize:
|
// give the Ethernet shield a second to initialize:
|
||||||
delay(1000);
|
delay(1000);
|
||||||
Serial.println("connecting...");
|
Serial.println("connecting...");
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
// Enter a MAC address and IP address for your controller below.
|
// Enter a MAC address and IP address for your controller below.
|
||||||
// The IP address will be dependent on your local network:
|
// The IP address will be dependent on your local network:
|
||||||
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||||
byte ip[] = { 192,168,1, 177 };
|
IPAddress ip(192,168,1, 177);
|
||||||
|
|
||||||
// Initialize the Ethernet server library
|
// Initialize the Ethernet server library
|
||||||
// with the IP address and port you want to use
|
// with the IP address and port you want to use
|
||||||
@ -79,4 +79,4 @@ void loop()
|
|||||||
// close the connection:
|
// close the connection:
|
||||||
client.stop();
|
client.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
Ethernet KEYWORD1
|
Ethernet KEYWORD1
|
||||||
Client KEYWORD1
|
Client KEYWORD1
|
||||||
Server KEYWORD1
|
Server KEYWORD1
|
||||||
|
IPAddress KEYWORD1
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Methods and Functions (KEYWORD2)
|
# Methods and Functions (KEYWORD2)
|
||||||
@ -19,10 +20,16 @@ connect KEYWORD2
|
|||||||
write KEYWORD2
|
write KEYWORD2
|
||||||
available KEYWORD2
|
available KEYWORD2
|
||||||
read KEYWORD2
|
read KEYWORD2
|
||||||
|
peek KEYWORD2
|
||||||
flush KEYWORD2
|
flush KEYWORD2
|
||||||
stop KEYWORD2
|
stop KEYWORD2
|
||||||
connected KEYWORD2
|
connected KEYWORD2
|
||||||
begin KEYWORD2
|
begin KEYWORD2
|
||||||
|
beginPacket KEYWORD2
|
||||||
|
endPacket KEYWORD2
|
||||||
|
parsePacket KEYWORD2
|
||||||
|
remoteIP KEYWORD2
|
||||||
|
remotePort KEYWORD2
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Constants (LITERAL1)
|
# Constants (LITERAL1)
|
||||||
|
13
libraries/Ethernet/util.h
Normal file
13
libraries/Ethernet/util.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef UTIL_H
|
||||||
|
#define UTIL_H
|
||||||
|
|
||||||
|
#define htons(x) ( (x)<<8 | ((x)>>8)&0xFF )
|
||||||
|
#define ntohs(x) htons(x)
|
||||||
|
|
||||||
|
#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \
|
||||||
|
((x)<< 8 & 0x00FF0000UL) | \
|
||||||
|
((x)>> 8 & 0x0000FF00UL) | \
|
||||||
|
((x)>>24 & 0x000000FFUL) )
|
||||||
|
#define ntohl(x) htonl(x)
|
||||||
|
|
||||||
|
#endif
|
@ -344,3 +344,58 @@ uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
|
||||||
|
{
|
||||||
|
uint16_t ret =0;
|
||||||
|
if (len > W5100.getTXFreeSize(s))
|
||||||
|
{
|
||||||
|
ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = len;
|
||||||
|
}
|
||||||
|
W5100.send_data_processing_offset(s, offset, buf, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int startUDP(SOCKET s, uint8_t* addr, uint16_t port)
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
|
||||||
|
((port == 0x00))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
W5100.writeSnDIPR(s, addr);
|
||||||
|
W5100.writeSnDPORT(s, port);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sendUDP(SOCKET s)
|
||||||
|
{
|
||||||
|
W5100.execCmdSn(s, Sock_SEND);
|
||||||
|
|
||||||
|
/* +2008.01 bj */
|
||||||
|
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
|
||||||
|
{
|
||||||
|
if (W5100.readSnIR(s) & SnIR::TIMEOUT)
|
||||||
|
{
|
||||||
|
/* +2008.01 [bj]: clear interrupt */
|
||||||
|
W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* +2008.01 bj */
|
||||||
|
W5100.writeSnIR(s, SnIR::SEND_OK);
|
||||||
|
|
||||||
|
/* Sent ok */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -16,5 +16,26 @@ extern uint16_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr,
|
|||||||
|
|
||||||
extern uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len);
|
extern uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len);
|
||||||
|
|
||||||
|
// Functions to allow buffered UDP send (i.e. where the UDP datagram is built up over a
|
||||||
|
// number of calls before being sent
|
||||||
|
/*
|
||||||
|
@brief This function sets up a UDP datagram, the data for which will be provided by one
|
||||||
|
or more calls to bufferData and then finally sent with sendUDP.
|
||||||
|
@return 1 if the datagram was successfully set up, or 0 if there was an error
|
||||||
|
*/
|
||||||
|
extern int startUDP(SOCKET s, uint8_t* addr, uint16_t port);
|
||||||
|
/*
|
||||||
|
@brief This function copies up to len bytes of data from buf into a UDP datagram to be
|
||||||
|
sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls.
|
||||||
|
@return Number of bytes successfully buffered
|
||||||
|
*/
|
||||||
|
uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len);
|
||||||
|
/*
|
||||||
|
@brief Send a UDP datagram built up from a sequence of startUDP followed by one or more
|
||||||
|
calls to bufferData.
|
||||||
|
@return 1 if the datagram was successfully sent, or 0 if there was an error
|
||||||
|
*/
|
||||||
|
int sendUDP(SOCKET s);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* _SOCKET_H_ */
|
/* _SOCKET_H_ */
|
||||||
|
@ -65,10 +65,16 @@ uint16_t W5100Class::getRXReceivedSize(SOCKET s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void W5100Class::send_data_processing(SOCKET s, uint8_t *data, uint16_t len)
|
void W5100Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len)
|
||||||
|
{
|
||||||
|
// This is same as having no offset in a call to send_data_processing_offset
|
||||||
|
send_data_processing_offset(s, 0, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void W5100Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
|
||||||
{
|
{
|
||||||
uint16_t ptr = readSnTX_WR(s);
|
uint16_t ptr = readSnTX_WR(s);
|
||||||
|
ptr += data_offset;
|
||||||
uint16_t offset = ptr & SMASK;
|
uint16_t offset = ptr & SMASK;
|
||||||
uint16_t dstAddr = offset + SBASE[s];
|
uint16_t dstAddr = offset + SBASE[s];
|
||||||
|
|
||||||
@ -132,7 +138,7 @@ uint8_t W5100Class::write(uint16_t _addr, uint8_t _data)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t W5100Class::write(uint16_t _addr, uint8_t *_buf, uint16_t _len)
|
uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len)
|
||||||
{
|
{
|
||||||
for (int i=0; i<_len; i++)
|
for (int i=0; i<_len; i++)
|
||||||
{
|
{
|
||||||
|
@ -146,7 +146,19 @@ public:
|
|||||||
* This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
|
* This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
|
||||||
* register. User should read upper byte first and lower byte later to get proper value.
|
* register. User should read upper byte first and lower byte later to get proper value.
|
||||||
*/
|
*/
|
||||||
void send_data_processing(SOCKET s, uint8_t *data, uint16_t len);
|
void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len);
|
||||||
|
/**
|
||||||
|
* @brief A copy of send_data_processing that uses the provided ptr for the
|
||||||
|
* write offset. Only needed for the "streaming" UDP API, where
|
||||||
|
* a single UDP packet is built up over a number of calls to
|
||||||
|
* send_data_processing_ptr, because TX_WR doesn't seem to get updated
|
||||||
|
* correctly in those scenarios
|
||||||
|
* @param ptr value to use in place of TX_WR. If 0, then the value is read
|
||||||
|
* in from TX_WR
|
||||||
|
* @return New value for ptr, to be used in the next call
|
||||||
|
*/
|
||||||
|
// FIXME Update documentation
|
||||||
|
void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function is being called by recv() also.
|
* @brief This function is being called by recv() also.
|
||||||
@ -182,7 +194,7 @@ public:
|
|||||||
// ---------------
|
// ---------------
|
||||||
private:
|
private:
|
||||||
static uint8_t write(uint16_t _addr, uint8_t _data);
|
static uint8_t write(uint16_t _addr, uint8_t _data);
|
||||||
static uint16_t write(uint16_t addr, uint8_t *buf, uint16_t len);
|
static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len);
|
||||||
static uint8_t read(uint16_t addr);
|
static uint8_t read(uint16_t addr);
|
||||||
static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len);
|
static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user