forked from espressif/arduino-esp32
Add Server and UDP and fix WiFi.hostByName
This commit is contained in:
@ -34,6 +34,8 @@
|
||||
#include "WiFiGeneric.h"
|
||||
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiServer.h"
|
||||
#include "WiFiUdp.h"
|
||||
|
||||
class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass
|
||||
{
|
||||
@ -55,6 +57,8 @@ public:
|
||||
public:
|
||||
void printDiag(Print& dest);
|
||||
friend class WiFiClient;
|
||||
friend class WiFiServer;
|
||||
friend class WiFiUDP;
|
||||
};
|
||||
|
||||
extern WiFiClass WiFi;
|
||||
|
@ -304,7 +304,21 @@ bool WiFiGenericClass::enableAP(bool enable)
|
||||
// ------------------------------------------------ Generic Network function ---------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg);
|
||||
static bool _dns_busy = false;
|
||||
|
||||
/**
|
||||
* DNS callback
|
||||
* @param name
|
||||
* @param ipaddr
|
||||
* @param callback_arg
|
||||
*/
|
||||
static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
|
||||
{
|
||||
if(ipaddr) {
|
||||
(*reinterpret_cast<IPAddress*>(callback_arg)) = ipaddr->u_addr.ip4.addr;
|
||||
}
|
||||
_dns_busy = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given hostname to an IP address.
|
||||
@ -313,36 +327,24 @@ void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *ca
|
||||
* @return 1 if aIPAddrString was successfully converted to an IP address,
|
||||
* else error code
|
||||
*/
|
||||
static bool _dns_busy = false;
|
||||
|
||||
int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult)
|
||||
{
|
||||
ip_addr_t addr;
|
||||
aResult = static_cast<uint32_t>(0);
|
||||
|
||||
_dns_busy = true;
|
||||
err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult);
|
||||
_dns_busy = err == ERR_INPROGRESS;
|
||||
while(_dns_busy);
|
||||
if(err == ERR_INPROGRESS && aResult) {
|
||||
//found by search
|
||||
} else if(err == ERR_OK && addr.u_addr.ip4.addr) {
|
||||
if(err == ERR_OK && addr.u_addr.ip4.addr) {
|
||||
aResult = addr.u_addr.ip4.addr;
|
||||
_dns_busy = false;
|
||||
} else if(err == ERR_INPROGRESS) {
|
||||
while(_dns_busy){
|
||||
delay(1);
|
||||
}
|
||||
} else {
|
||||
_dns_busy = false;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* DNS callback
|
||||
* @param name
|
||||
* @param ipaddr
|
||||
* @param callback_arg
|
||||
*/
|
||||
void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
|
||||
{
|
||||
if(ipaddr) {
|
||||
(*reinterpret_cast<IPAddress*>(callback_arg)) = ipaddr->u_addr.ip4.addr;
|
||||
}
|
||||
_dns_busy = false;
|
||||
}
|
||||
|
||||
|
77
libraries/WiFi/src/WiFiServer.cpp
Normal file
77
libraries/WiFi/src/WiFiServer.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
Server.cpp - Server class for Raspberry Pi
|
||||
Copyright (c) 2016 Hristo Gochkov All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "WiFiServer.h"
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
|
||||
#undef write
|
||||
|
||||
int WiFiServer::setTimeout(uint32_t seconds){
|
||||
struct timeval tv;
|
||||
tv.tv_sec = seconds;
|
||||
tv.tv_usec = 0;
|
||||
if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0)
|
||||
return -1;
|
||||
return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));
|
||||
}
|
||||
|
||||
size_t WiFiServer::write(const uint8_t *data, size_t len){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WiFiServer::stopAll(){}
|
||||
|
||||
WiFiClient WiFiServer::available(){
|
||||
if(!_listening)
|
||||
return WiFiClient();
|
||||
struct sockaddr_in _client;
|
||||
int cs = sizeof(struct sockaddr_in);
|
||||
int client_sock = accept(sockfd, (struct sockaddr *)&_client, (socklen_t*)&cs);
|
||||
if(client_sock >= 0){
|
||||
int val = 1;
|
||||
if(setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(int)) == ESP_OK)
|
||||
return WiFiClient(client_sock);
|
||||
}
|
||||
return WiFiClient();
|
||||
}
|
||||
|
||||
void WiFiServer::begin(){
|
||||
if(_listening)
|
||||
return;
|
||||
struct sockaddr_in server;
|
||||
sockfd = socket(AF_INET , SOCK_STREAM, 0);
|
||||
if (sockfd < 0)
|
||||
return;
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = INADDR_ANY;
|
||||
server.sin_port = htons(_port);
|
||||
if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
|
||||
return;
|
||||
if(listen(sockfd , _max_clients) < 0)
|
||||
return;
|
||||
fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||
_listening = true;
|
||||
}
|
||||
|
||||
void WiFiServer::end(){
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
_listening = false;
|
||||
}
|
||||
|
53
libraries/WiFi/src/WiFiServer.h
Normal file
53
libraries/WiFi/src/WiFiServer.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Server.h - Server class for Raspberry Pi
|
||||
Copyright (c) 2016 Hristo Gochkov All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _WIFISERVER_H_
|
||||
#define _WIFISERVER_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Server.h"
|
||||
#include "WiFiClient.h"
|
||||
|
||||
class WiFiServer : public Server {
|
||||
private:
|
||||
int sockfd;
|
||||
uint16_t _port;
|
||||
uint8_t _max_clients;
|
||||
bool _listening;
|
||||
|
||||
public:
|
||||
void listenOnLocalhost(){}
|
||||
|
||||
WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_port(port),_max_clients(max_clients),_listening(false){}
|
||||
~WiFiServer(){ end();}
|
||||
WiFiClient available();
|
||||
WiFiClient accept(){return available();}
|
||||
void begin();
|
||||
size_t write(const uint8_t *data, size_t len);
|
||||
size_t write(uint8_t data){
|
||||
return write(&data, 1);
|
||||
}
|
||||
using Print::write;
|
||||
|
||||
void end();
|
||||
operator bool(){return _listening;}
|
||||
int setTimeout(uint32_t seconds);
|
||||
void stopAll();
|
||||
};
|
||||
|
||||
#endif /* _WIFISERVER_H_ */
|
254
libraries/WiFi/src/WiFiUdp.cpp
Normal file
254
libraries/WiFi/src/WiFiUdp.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
Udp.cpp - UDP class for Raspberry Pi
|
||||
Copyright (c) 2016 Hristo Gochkov All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "WiFiUdp.h"
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include <errno.h>
|
||||
|
||||
#undef write
|
||||
#undef read
|
||||
|
||||
WiFiUDP::WiFiUDP()
|
||||
: udp_server(-1)
|
||||
, server_port(0)
|
||||
, remote_port(0)
|
||||
, tx_buffer(0)
|
||||
, tx_buffer_len(0)
|
||||
, rx_buffer(0)
|
||||
{}
|
||||
|
||||
WiFiUDP::~WiFiUDP(){
|
||||
stop();
|
||||
}
|
||||
|
||||
uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){
|
||||
stop();
|
||||
|
||||
server_port = port;
|
||||
|
||||
tx_buffer = new char[1460];
|
||||
if(!tx_buffer){
|
||||
log_e("could not create tx buffer: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((udp_server=socket(AF_INET, SOCK_DGRAM, 0)) == -1){
|
||||
log_e("could not create socket: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yes = 1;
|
||||
if (setsockopt(udp_server,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
|
||||
log_e("could not set socket option: %d", errno);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset((char *) &addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(server_port);
|
||||
addr.sin_addr.s_addr = (in_addr_t)address;
|
||||
if(bind(udp_server , (struct sockaddr*)&addr, sizeof(addr)) == -1){
|
||||
log_e("could not bind socket: %d", errno);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
fcntl(udp_server, F_SETFL, O_NONBLOCK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t WiFiUDP::begin(uint16_t p){
|
||||
return begin(IPAddress(INADDR_ANY), p);
|
||||
}
|
||||
|
||||
uint8_t WiFiUDP::beginMulticast(IPAddress a, uint16_t p){
|
||||
if(begin(IPAddress(INADDR_ANY), p)){
|
||||
if(a != 0){
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = (in_addr_t)a;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
if (setsockopt(udp_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
|
||||
log_e("could not join igmp: %d", errno);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
multicast_ip = a;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WiFiUDP::stop(){
|
||||
if(tx_buffer){
|
||||
delete[] tx_buffer;
|
||||
}
|
||||
tx_buffer_len = 0;
|
||||
if(rx_buffer){
|
||||
cbuf *b = rx_buffer;
|
||||
rx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
if(udp_server == -1)
|
||||
return;
|
||||
if(multicast_ip != 0){
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = (in_addr_t)multicast_ip;
|
||||
mreq.imr_interface.s_addr = (in_addr_t)0;
|
||||
setsockopt(udp_server, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
|
||||
multicast_ip = IPAddress(INADDR_ANY);
|
||||
}
|
||||
close(udp_server);
|
||||
udp_server = -1;
|
||||
}
|
||||
|
||||
int WiFiUDP::beginMulticastPacket(){
|
||||
if(!server_port || multicast_ip == IPAddress(INADDR_ANY))
|
||||
return 0;
|
||||
remote_ip = server_port;
|
||||
remote_port = multicast_ip;
|
||||
return beginPacket();
|
||||
}
|
||||
|
||||
int WiFiUDP::beginPacket(){
|
||||
if(!remote_port)
|
||||
return 0;
|
||||
tx_buffer_len = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port){
|
||||
remote_ip = ip;
|
||||
remote_port = port;
|
||||
return beginPacket();
|
||||
}
|
||||
|
||||
int WiFiUDP::beginPacket(const char *host, uint16_t port){
|
||||
struct hostent *server;
|
||||
server = gethostbyname(host);
|
||||
if (server == NULL){
|
||||
log_e("could not get host from dns: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
return beginPacket(IPAddress((const uint8_t *)(server->h_addr_list[0])), port);
|
||||
}
|
||||
|
||||
int WiFiUDP::endPacket(){
|
||||
struct sockaddr_in recipient;
|
||||
recipient.sin_addr.s_addr = (uint32_t)remote_ip;
|
||||
recipient.sin_family = AF_INET;
|
||||
recipient.sin_port = htons(remote_port);
|
||||
int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient));
|
||||
if(sent < 0){
|
||||
log_e("could not send data: %d", errno);
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
|
||||
size_t WiFiUDP::write(uint8_t data){
|
||||
if(tx_buffer_len == 1460){
|
||||
endPacket();
|
||||
tx_buffer_len = 0;
|
||||
}
|
||||
tx_buffer[tx_buffer_len++] = data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t WiFiUDP::write(const uint8_t *buffer, size_t size){
|
||||
size_t i;
|
||||
for(i=0;i<size;i++)
|
||||
write(buffer[i]);
|
||||
return i;
|
||||
}
|
||||
|
||||
int WiFiUDP::parsePacket(){
|
||||
if(rx_buffer)
|
||||
return 0;
|
||||
struct sockaddr_in si_other;
|
||||
int slen = sizeof(si_other) , len;
|
||||
char * buf = new char[1460];
|
||||
if(!buf){
|
||||
return 0;
|
||||
}
|
||||
if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *) &si_other, (socklen_t *)&slen)) == -1){
|
||||
delete[] buf;
|
||||
if(errno == EWOULDBLOCK){
|
||||
return 0;
|
||||
}
|
||||
log_e("could not receive data: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
remote_ip = IPAddress(si_other.sin_addr.s_addr);
|
||||
remote_port = ntohs(si_other.sin_port);
|
||||
rx_buffer = new cbuf(len);
|
||||
rx_buffer->write(buf, len);
|
||||
delete[] buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
int WiFiUDP::available(){
|
||||
if(!rx_buffer) return 0;
|
||||
return rx_buffer->size();
|
||||
}
|
||||
|
||||
int WiFiUDP::read(){
|
||||
if(!rx_buffer) return -1;
|
||||
int out = rx_buffer->read();
|
||||
if(!rx_buffer->size()){
|
||||
cbuf *b = rx_buffer;
|
||||
rx_buffer = 0;
|
||||
delete b;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int WiFiUDP::read(unsigned char* buffer, size_t len){
|
||||
return read((char *)buffer, len);
|
||||
}
|
||||
|
||||
int WiFiUDP::read(char* buffer, size_t len){
|
||||
if(!rx_buffer) return 0;
|
||||
int out = rx_buffer->read(buffer, len);
|
||||
if(!rx_buffer->size()){
|
||||
cbuf *b = rx_buffer;
|
||||
rx_buffer = 0;
|
||||
delete b;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int WiFiUDP::peek(){
|
||||
if(!rx_buffer) return -1;
|
||||
return rx_buffer->peek();
|
||||
}
|
||||
|
||||
void WiFiUDP::flush(){
|
||||
cbuf *b = rx_buffer;
|
||||
rx_buffer = 0;
|
||||
delete b;
|
||||
}
|
||||
|
||||
IPAddress WiFiUDP::remoteIP(){
|
||||
return remote_ip;
|
||||
}
|
||||
|
||||
uint16_t WiFiUDP::remotePort(){
|
||||
return remote_port;
|
||||
}
|
77
libraries/WiFi/src/WiFiUdp.h
Normal file
77
libraries/WiFi/src/WiFiUdp.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Udp.cpp: Library to send/receive UDP packets.
|
||||
*
|
||||
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
|
||||
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
|
||||
* might not happen often in practice, but in larger network topologies, a UDP
|
||||
* packet can be received out of sequence.
|
||||
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
|
||||
* aware of it. Again, this may not be a concern in practice on small local networks.
|
||||
* For more information, see http://www.cafeaulait.org/course/week12/35.html
|
||||
*
|
||||
* MIT License:
|
||||
* Copyright (c) 2008 Bjoern Hartmann
|
||||
* 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.
|
||||
*
|
||||
* bjoern@cs.stanford.edu 12/30/2008
|
||||
*/
|
||||
|
||||
#ifndef _WIFIUDP_H_
|
||||
#define _WIFIUDP_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Udp.h>
|
||||
#include <cbuf.h>
|
||||
|
||||
class WiFiUDP : public UDP {
|
||||
private:
|
||||
int udp_server;
|
||||
IPAddress multicast_ip;
|
||||
IPAddress remote_ip;
|
||||
uint16_t server_port;
|
||||
uint16_t remote_port;
|
||||
char * tx_buffer;
|
||||
size_t tx_buffer_len;
|
||||
cbuf * rx_buffer;
|
||||
public:
|
||||
WiFiUDP();
|
||||
~WiFiUDP();
|
||||
uint8_t begin(IPAddress a, uint16_t p);
|
||||
uint8_t begin(uint16_t p);
|
||||
uint8_t beginMulticast(IPAddress a, uint16_t p);
|
||||
void stop();
|
||||
int beginMulticastPacket();
|
||||
int beginPacket();
|
||||
int beginPacket(IPAddress ip, uint16_t port);
|
||||
int beginPacket(const char *host, uint16_t port);
|
||||
int endPacket();
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
int parsePacket();
|
||||
int available();
|
||||
int read();
|
||||
int read(unsigned char* buffer, size_t len);
|
||||
int read(char* buffer, size_t len);
|
||||
int peek();
|
||||
void flush();
|
||||
IPAddress remoteIP();
|
||||
uint16_t remotePort();
|
||||
};
|
||||
|
||||
#endif /* _WIFIUDP_H_ */
|
Reference in New Issue
Block a user