mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-20 21:01:25 +03:00
Fix for issue 439. UDP API changed to derive from Stream. The old sendPacket and readPacket calls have been removed, and replaced with Stream-derived alternatives which provide more commonality with other communications classes and to allow both buffered and full-packet-at-a-time uses. Also includes the introduction of an IPAddress class to make passing them around easier (and require fewer pointers to be exposed)
This commit is contained in:
39
libraries/Ethernet/IPAddress.cpp
Normal file
39
libraries/Ethernet/IPAddress.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
#include <WProgram.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;
|
||||||
|
}
|
||||||
|
|
55
libraries/Ethernet/IPAddress.h
Normal file
55
libraries/Ethernet/IPAddress.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
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 uint8_t*() { return _address; };
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
};
|
||||||
|
|
||||||
|
#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, 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,57 @@
|
|||||||
#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);
|
||||||
|
// 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
|
||||||
|
@ -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((byte*)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);
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,12 @@
|
|||||||
// 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[] = {
|
|
||||||
192,168,1,177 };
|
|
||||||
|
|
||||||
|
IPAddress 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
|
||||||
|
|
||||||
@ -55,8 +53,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:
|
||||||
@ -118,7 +117,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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