Running WebServerSecure and PubSubClient on ESP8266 - webserver

I wrote a sketch for ESP8266. This sketch reads some sensor data and published it via MQTT. In addition I want to let a Web server provide the same data as HTML, or JSON web service.
The MQTT publish is triggered via a TaskScheduler timer.
Both functions, MQTT and Web server, work for itself, but sadly not together. Here's a simplified sketch:
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServerSecure.h>
#include <PubSubClient.h>
#include <TaskScheduler.h>
#include <My_WLAN.h> // provices connection to local WLAN and network settings
const char DNS_NAME[] = "myserver.local";
const int HTTPS_PORT = 443; // HTTPS
const char MQTT_SVR[] = "myserver.local";
const unsigned int MQTT_PORT = 8883; // MQTTS
WiFiClientSecure wifiClient;
PubSubClient mqttClient(wifiClient); // MQTT client instance
ESP8266WebServerSecure server(HTTPS_PORT); // web server instance
void t1Callback(void); // callback method prototypes
Task t1(60000, TASK_FOREVER, &t1Callback); // main loop task
Scheduler timer; // task scheduler
static const uint8_t SVR_FINGERPRINT[20] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20 };
static const char deviceCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
[... certificate ...]
-----END CERTIFICATE-----
)EOF";
static const char deviceKey[] PROGMEM = R"EOF(
-----BEGIN RSA PRIVATE KEY-----
[... key ...]
-----END RSA PRIVATE KEY-----
)EOF";
/* *****************************
MQTT_connect
* *****************************/
void MQTT_connect()
{
int attempt = 0;
/* loop until reconnected */
while (!mqttClient.connected() && attempt < 10) {
attempt++;
Serial.print("Attempting MQTT connection ("); Serial.print(attempt); Serial.print(")...");
mqttClient.setServer(MQTT_SVR, MQTT_PORT);
if (mqttClient.connect(DNS_NAME)) {
Serial.println("success");
} else {
Serial.print("failed, status code = "); Serial.print(mqttClient.state());
Serial.println(". - Try again in 5 seconds...");
delay(5000);
}
}
}
/* *****************************
Web Server handleRoot
* *****************************/
void handleRoot() {
digitalWrite(LED_BUILTIN, LOW); // on
Serial.println("WebServer ROOT");
server.send(200, "text/html", "WebServer ROOT");
digitalWrite(LED_BUILTIN, HIGH); // off
}
/* *****************************
Web Server handleNotFound
* *****************************/
void handleNotFound() {
digitalWrite(LED_BUILTIN, LOW); // on
String message = "File not found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
digitalWrite(LED_BUILTIN, HIGH); // off
}
/* *************************
MQTT_publish_something
* *************************/
void MQTT_publish_something() {
digitalWrite(LED_BUILTIN, LOW); // on
char payload[30] = "some_payload_data";
if (!mqttClient.publish("MQTT/Test", payload, true)) { // retain message
Serial.println("MQTT message lost!");
}
digitalWrite(LED_BUILTIN, HIGH); // off
}
/* *************************
t1: main timer (callback)
* *************************/
void t1Callback() {
my.WiFi_connect(); // check and re-connect to WLAN (in My_WLAN.h)
if (WiFi.status() == WL_CONNECTED) {
MQTT_connect();
MQTT_publish_something();
}
}
/* *************************
setup
* *************************/
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // internal LED
digitalWrite(LED_BUILTIN, HIGH); // off
/* -----------------------
open Serial |
----------------------- */
Serial.begin(74880);
while (!Serial); // wait for Serial being ready
/* -----------------------
connect to WLAN |
----------------------- */
my.WiFi_connect(); // this is connecting to WLAN & error handling (in My_WLAN.h)
wifiClient.setFingerprint(SVR_FINGERPRINT);
/* -----------------------
set mDNS |
----------------------- */
if (MDNS.begin(DNS_NAME)) {
Serial.printf("mDNS responder started for %s\n", DNS_NAME);
MDNS.addService("https", "tcp", HTTPS_PORT); // add service to MDNS-SD
MDNS.addService("mqtt", "tcp", MQTT_PORT);
} else
Serial.println("Error setting up mDNS responder!");
/* -----------------------
start HTTPS server |
----------------------- */
server.getServer().setRSACert(new X509List(deviceCert), new PrivateKey(deviceKey));
server.on("/", handleRoot); // standard HTML root
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTPS server started.");
Serial.println();
/* -----------------------
start timer |
----------------------- */
timer.init();
timer.addTask(t1);
// line 177:
timer.enableAll();
}
void loop() {
MDNS.update();
// line 184:
server.handleClient();
mqttClient.loop();
timer.execute();
}
Running MQTT only works fine and publishes data (I use the mosquitto broker).
Running the Web server (https://...) works fine as well, if commenting out line 177 (so MQTT does not get triggered).
With both functions active, as soon as the first MQTT message had been sent, the web server does not answer any more. I get PR_END_OF_FILE_ERROR in FF and ERR_CONNECTION_CLOSED in Chrome.
I guess, that these libraries somehow mess with each other, or that something confuses with the certificates. However, the fingerprint belongs to the server running mosquitto, while the X509 certificate belongs to the web server running on the ESP8266. These are two different machines and have nothing to do with each other.
Any idea welcome.

I suspect both libraries use port 443, and you can only have one listener on a given port. I've tried creating a BearSSL::ESP8266WebServerSecure object with alternate ports, such as 80 and 8443 but can't get them to work. Worse, there doesn't seem to be a way to stop a listener once a BearSSL::ESP8266WebServerSecure object has started, so it can't be released for later reuse.
I ended up using HTTP to get WiFi credentials, then HTTPS from there on out. Not a very satisfactory solution but it works.
Update: I was able to run a provisioning server on port 443, stop it by calling
BearSSL::ESP8266WebServerSecure provisioningServer(443);
BearSSL::ESP8266WebServerSecure server(443);
provisioningServer.close();
provisioningServer.~ESP8266WebServerSecure(); // note: cannot use TLS on both servers without this line
After calling the provisioning server's destructor I was able to start my server on port 443.

Related

Boost Beast async rest client : async_resolve - resolve: Host not found (authoritative)

I have the async boost rest client code. I am able to compile and run this code using Cygwin on Windows.
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
namespace http = boost::beast::http; // from <boost/beast/http.hpp>
void
fail(boost::system::error_code ec, char const* what)
{
std::cerr << what << ": " << ec.message() << "\n";
}
// Performs an HTTP GET and prints the response
class session : public std::enable_shared_from_this<session>
{
tcp::resolver resolver_;
tcp::socket socket_;
boost::beast::flat_buffer buffer_; // (Must persist between reads)
http::request<http::empty_body> req_;
http::response<http::string_body> res_;
public:
// Resolver and socket require an io_context
explicit
session(boost::asio::io_context& ioc)
: resolver_(ioc)
, socket_(ioc)
{
}
// Start the asynchronous operation
void
run(char const* host, char const* port, char const* target, int version)
{
// Set up an HTTP GET request message
req_.version(version);
req_.method(http::verb::get);
req_.target(target);
req_.set(http::field::host, host);
req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
// Look up the domain name
resolver_.async_resolve(host, port,std::bind( &session::on_resolve, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
void
on_resolve( boost::system::error_code ec, tcp::resolver::results_type results)
{
if(ec) {
return fail(ec, "resolve");
}
// Make the connection on the IP address we get from a lookup
boost::asio::async_connect(socket_,results.begin(),results.end(),std::bind(&session::on_connect,shared_from_this(), std::placeholders::_1));
}
void
on_connect(boost::system::error_code ec)
{
if(ec) {
return fail(ec, "connect");
}
// Send the HTTP request to the remote host
http::async_write(socket_, req_,std::bind(&session::on_write, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
void
on_write( boost::system::error_code ec, std::size_t bytes_transferred)
{
boost::ignore_unused(bytes_transferred);
if(ec) {
return fail(ec, "write");
}
// Receive the HTTP response
http::async_read(socket_, buffer_, res_, std::bind( &session::on_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
void
on_read(boost::system::error_code ec, std::size_t bytes_transferred)
{
boost::ignore_unused(bytes_transferred);
if(ec) {
return fail(ec, "read");
}
// Write the message to standard out
std::cout << res_ << std::endl;
// Gracefully close the socket
socket_.shutdown(tcp::socket::shutdown_both, ec);
// not_connected happens sometimes so don't bother reporting it.
if(ec && ec != boost::system::errc::not_connected) {
return fail(ec, "shutdown");
}
// If we get here then the connection is closed gracefully
}
};
int main(int argc, char** argv)
{
// Check command line arguments.
if(argc != 4 && argc != 5)
{
std::cerr <<
"Usage: http-client-async <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
"Example:\n" <<
" http-client-async www.example.com 80 /\n" <<
" http-client-async www.example.com 80 / 1.0\n";
return EXIT_FAILURE;
}
auto const host = argv[1];
auto const port = argv[2];
auto const target = argv[3];
int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
// The io_context is required for all I/O
boost::asio::io_context ioc;
// Launch the asynchronous operation
std::make_shared<session>(ioc)->run(host, port, target, version);
// Run the I/O service. The call will return when
// the get operation is complete.
ioc.run();
return EXIT_SUCCESS;
}
I have a python REST Server that runs waiting for requests from this client.
#!flask/bin/python
from flask import Flask, jsonify
app = Flask(__name__)
tasks = [
{
'id': 1,
'title': u'Buy groceries',
'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
'done': False
},
{
'id': 2,
'title': u'Learn Python',
'description': u'Need to find a good Python tutorial on the web',
'done': False
}
]
#app.route('/todo/api/v1.0/tasks', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})
if __name__ == '__main__':
app.run(host='0.0.0.0',debug=True)
I am able to run this server. The output is shown below.
* Serving Flask app 'RESTServer' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployme
nt.
Use a production WSGI server instead.
* Debug mode: on
* Restarting with stat
* Debugger is active!
* Debugger PIN: 409-562-797
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployme
nt.
* Running on http://192.168.1.104:5000/ (Press CTRL+C to quit)
However when I run the REST Client, as below
rest_client.exe http://192.168.1.104 5000 /todo/api/v1.0/tasks
I get the following error
resolve: Host not found (authoritative)
The program expects separate arguments. It even gives you usage instructions:
Usage: http-client-async <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]
Example:
http-client-async www.example.com 80 /
http-client-async www.example.com 80 / 1.0
So it looks like you AT LEAST want to remove http://

Using both TCP and UDP protocols seem not to work on Ethernet Shield w5100

I'm having a problem using both TCP and UDP in the same sketch. What appears to happen is that if the same socket is reused for UDP after it was in use for TCP, UPD fails to receive data. I was able to reproduce this with the WebServer example. I've added to it a DNS query once in every 10 seconds to query yahoo.com IP address. The DSN queries succeed if I'm not creating any client traffic from the browser. After I query the server over HTTP over TCP, the DSN queries start to fail. DNS queries are implemented in UDP. This is the code that I'm using:
/*
Web Server
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified 02 Sept 2015
by Arturo Guadalupi
*/
#include <SPI.h>
#include <Ethernet.h>
#include <Dns.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
unsigned long t0;
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
//Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
t0 = millis();
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
if (millis() - t0 > 10000)
{
DNSClient dns;
dns.begin(IPAddress(8,8,8,8));
IPAddress yahoo;
if (dns.getHostByName("yahoo.com", yahoo) == 1)
{
Serial.print("Yahoo: ");
Serial.print(yahoo[0]);
Serial.print(".");
Serial.print(yahoo[1]);
Serial.print(".");
Serial.print(yahoo[2]);
Serial.print(".");
Serial.println(yahoo[3]);
}
else
{
Serial.println("Failed to query yahoo.com IP address");
}
t0 = millis();
}
}
Is this a known issue? Can someone please help in identifying the problem in my code, or if there is a workaround for this issue? Can it be a hardware issue? I'm using SunFounder boards, not the original Arduino boards.
Thanks a lot,
Boaz,

Unable to send publish messages from esp8266 to Raspberry (Broker) using MQTT. Getting Socket Error <Random Device Id>, Disconnecting

I am trying to send and receive a messages from Raspberry Pi (Broker) to Arduino-ESP8266 (client) using MQTT. What I am trying to achieve is pretty basic for now. The broker sends a start command and the client on receving the message should send back a random number. I am able to read the message sent by the broker but the messages from the client are never sent. Here is the code that I am using
#include <WiFiEsp.h>
#include <WiFiEspClient.h>
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(19, 18); //RX, TX
#endif
#define MQTT_KEEPALIVE 10
#include <PubSubClient.h>
IPAddress server(192, 168, 0, 105);
char ssid[] = "user1956";
char password[] = "******";
int status = WL_IDLE_STATUS; //wifi radio's status
//MQTT
//const char* mqtt_topic = "Rpi_Master";
const char* mqtt_username = "pi";
const char* mqtt_password = "********";
//client Id
const char* clientID = "A_2";
//Variables for numbers
long randNumber1;
String rn1;
char rn1_char[50];
WiFiEspClient wifiClient;
PubSubClient client(wifiClient); //1883 is the listener port for the broker
void setup() {
// Initilize serial for debugging
Serial.begin(115200);
//initilize serial for ESP module
Serial1.begin(115200);
//initilize the ESP module
WiFi.init(&Serial1);
if (WiFi.status() == WL_NO_SHIELD)
{
Serial.println("WiFi shield not present");
while (true);
}
while (status != WL_CONNECTED)
{
Serial.print("Attempting to connect to WPA SSID : ");
Serial.println(ssid);
status = WiFi.begin(ssid, password);
}
Serial.println("You are connected to the network");
client.setServer(server, 1883);
client.setCallback(callback);
//Allow the hardware to sort itself
delay(1500);
randomSeed(50);
}
void callback(char* topic, byte* payload, unsigned int length)
{
Serial.print("Message Received: [");
Serial.print(topic);
Serial.println("]");
Serial.print("Message is:");
String message = (char *)payload;
Serial.println(message);
else if (!strncmp((char *)payload, "B1", length)) //Start code can be changed to any string value in place of 1
{
client.publish("Ad_B", "OK");
generateRandomData();
}
else if (!strncmp((char *)payload, "B2", length)) //Start code can be changed to any string value in place of 1
{
client.publish("Ad_B", "OK");
generateRandomData();
}
}
void loop()
{
if (!client.connected())
{
reconnect();
}
client.loop();
delay(1000);
}
void reconnect()
{
while (!client.connected())
{
Serial.print("Attempting MQTT Connection...");
//Attempt to Connect
if (client.connect(clientID, mqtt_username, mqtt_password))
{
Serial.println("connected");
//Once connected publish an announcement
client.publish("Ad_B", "Ready");
//and resubscribe
client.subscribe("Rpi_Master"); //This name can be changed
}
else
{
Serial.print("failed, rc = ");
Serial.print(client.state());
Serial.println("Trying again in 5 seconds");
//Wait for 5 seconds before retrying
delay(5000);
}
}
}
void generateRandomData(){
randNumber1 = random(0,0); //(14000,15000)
//Serial.println(randNumber1); // print a random number from 0to 299
rn1 = String(randNumber1);
rn1.toCharArray(rn1_char, rn1.length() + 1);
client.publish("LC_B_1", rn1_char);
client.publish("Ad_B", "End");
}
This is the output of the serial monitor that I am receiving:
07:45:42.016 -> [WiFiEsp] Initializing ESP module
07:45:45.430 -> [WiFiEsp] Initilization successful - 1.5.4
07:45:45.430 -> Attempting to connect to WPA SSID : No Free Wifi
07:45:50.464 -> [WiFiEsp] Connected to No Free Wifi
07:45:50.464 -> You are connected to the network
07:45:51.940 -> Attempting MQTT Connection...[WiFiEsp] Connecting to 192.168.0.105
07:45:52.084 -> connected
07:46:31.926 -> Message Received: [Rpi_Master]
07:46:31.926 -> Message is:B2ter
07:46:37.438 -> [WiFiEsp] TIMEOUT: 20
08:20:58.967 -> [WiFiEsp] >>> TIMEOUT >>>
The client is unable to publish any messages. The mosquitto log shows PINGREQ and RINGRESP to a random id and client.publish stops with the following message in the log - Socket Error on Client <Some Random Client Id>, Disconnecting. Attached the screenshot of the log. Is there any way to know what the unknown client is? Please help me to sort this issue. Thanks.
You generateRandom() function blocks (15 seconds) for longer than the keep alive (10 seconds) timeout and this will block the client.loop() function so it will not be able to send keep alive packets.

Ethernet Shield Not Appearing on Network

I am currently working on a project that involves an arduino uno and an ethernet shield. I am using a sketch from Randomnerdtutorials.com (with slight changes to fit my router) which I will provide. The server that the ethernet shield creates does show up and work when I put the IP address in the URL bar (192.168.1.178:8080) The ethernet shield itself however does not show up on my list of attached devices to my Netgear router. It does occasionally but then disappears. Any ideas? I looked at another thread that stated to replace
Ethernet.begin(mac, ip, gateway, subnet);
with
Ethernet.begin(mac);
but that did not work. Any ideas are welcome. Here is the full code
/*
Created by Rui Santos
Visit: http://randomnerdtutorials.com for more arduino projects
Arduino with Ethernet Shield
*/
#include <SPI.h>
#include <Ethernet.h>
#include <Servo.h>
int led = 4;
Servo microservo;
int pos = 0;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 178 }; // ip in lan (that's what you need to use in your browser. ("192.168.1.178")
byte gateway[] = { 192, 168, 1, 130 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(8080); //server port
String readString;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
pinMode(led, OUTPUT);
microservo.attach(7);
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip, gateway, subnet);
// Ethernet.begin(mac);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// Create a client connection
EthernetClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();
//read char by char HTTP request
if (readString.length() < 100) {
//store characters to string
readString += c;
//Serial.print(c);
}
//if HTTP request has ended
if (c == '\n') {
Serial.println(readString); //print to serial monitor for debuging
client.println("HTTP/1.1 200 OK"); //send new page
client.println("Content-Type: text/html");
client.println();
client.println("<HTML>");
client.println("<HEAD>");
client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
client.println("<link rel='stylesheet' type='text/css' href='http://randomnerdtutorials.com/ethernetcss.css' />");
client.println("<TITLE>Random Nerd Tutorials Project</TITLE>");
client.println("</HEAD>");
client.println("<BODY>");
client.println("<H1>Random Nerd Tutorials Project</H1>");
client.println("<hr />");
client.println("<br />");
client.println("<H2>Arduino with Ethernet Shield</H2>");
client.println("<br />");
client.println("Turn On LED");
client.println("Turn Off LED<br />");
client.println("<br />");
client.println("<br />");
client.println("Rotate Left");
client.println("Rotate Right<br />");
client.println("<p>Created by Rui Santos. Visit http://randomnerdtutorials.com for more projects!</p>");
client.println("<br />");
client.println("</BODY>");
client.println("</HTML>");
delay(1);
//stopping client
client.stop();
//controls the Arduino if you press the buttons
if (readString.indexOf("?button1on") >0){
digitalWrite(led, HIGH);
}
if (readString.indexOf("?button1off") >0){
digitalWrite(led, LOW);
}
if (readString.indexOf("?button2on") >0){
for(pos = 0; pos < 180; pos += 3) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
microservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
if (readString.indexOf("?button2off") >0){
for(pos = 180; pos>=1; pos-=3) // goes from 180 degrees to 0 degrees
{
microservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
//clearing string for next read
readString="";
}
}
}
}
}
Looks like the problem is with DHCP. Try
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
else{Serial.println("DHCP OK!");
and see if it gives DHCP failure

C++ TCP Proxy and Socket Programming

Okay, I've scoured the net (literally) for the last ten hours, but no one seems to have a tutorial explaining how to create a C++ Proxy server in Windows. Several times I've run into functions that work solely for UNIX, and it's been a frustrating experience. I am VERY new to socket programming, but I need to have this finished within 48 hours. It seems impossible right now.
Requirements for the program:
The daemon listens for TCP connections on a specified port number.
When a new client initiates a TCP connection request, the daemon accepts
the request and establishes a TCP connection with the new client.
The daemon forks a child process that is dedicated to handling the new
client.
The child process establishes a TCP connection to a pre-assigned port on the
actual targeted server.
The child process falls into a loop in which it acts as an intermediator
exchanging data (reading/writing or writing/reading) between the client and
the targeted server.
Once a child has been forked, the daemon process resumes listening for
additional TCP connections.
I've run a provided winsock client and program to get a better idea of how sockets work, but it's getting me nowhere fast. pid_t is unavailable for windows, so forking is out of the question (or so I've gathered from the 10 hours of net-scouring).
If you can point me in the right direction for being able to use Internet Explorer's proxy settings (the IP and Port number feature) in combination with the program to yield webpages that are redirected to another server, that would be great.
/* client.c - code for example client program that uses TCP */
#ifndef unix
#include<winsock2.h>
#include <windows.h>
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#endif
#include <stdio.h>
#include <string.h>
#include <iostream>
#define PROTOPORT 5193 /* default protocol port number */
extern "C";
char localhost[] = "localhost"; /* default host name */
#define QLEN 6 /* size of request queue */
int visits = 0; /* counts client connections */
/*------------------------------------------------------------------------
* Program: client
*
* Purpose: allocate a socket, connect to a server, and print all output
*
* Syntax: client [ host [port] ]
*
* host - name of a computer on which server is executing
* port - protocol port number server is using
*
* Note: Both arguments are optional. If no host name is specified,
* the client uses "localhost"; if no protocol port is
* specified, the client uses the default given by PROTOPORT.
*
*------------------------------------------------------------------------
*/
int main(int argc, char *argv[])
{
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold an IP address */
int port; /* protocol port number */
char *host; /* pointer to host name */
int n; /* number of characters read */
char buf[1000]; /* buffer for data from the server */
struct sockaddr_in cad; /* structure to hold client's address */
int sd, sd2; /* socket descriptors */
int alen; /* length of address */
#ifdef WIN32
WSADATA wsaData;
WSAStartup(0x0101, &wsaData);
#endif
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */
/* Check command-line argument for protocol port and extract */
/* port number if one is specified. Otherwise, use the default */
/* port value given by constant PROTOPORT */
if (argc > 2) { /* if protocol port specified */
port = atoi(argv[2]); /* convert to binary */
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for legal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[2]);
exit(1);
if (argc > 1) { /* if argument specified */
port = atoi(argv[1]); /* convert argument to binary */
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for illegal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[1]);
exit(1);
}
/* Map TCP transport protocol name to protocol number */
(int)(ptrp = getprotobyname("tcp"));
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Check host argument and assign host name. */
if (argc > 1) {
host = argv[1]; /* if host argument specified */
} else {
host = localhost;
}
/* Convert host name to equivalent IP address and copy to sad. */
ptrh = gethostbyname(host);
if ( ((char *)ptrh) == NULL ) {
fprintf(stderr,"invalid host: %s\n", host);
exit(1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
/* Map TCP transport protocol name to protocol number. */
(int)(ptrp = getprotobyname("tcp"));
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a socket. */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Connect the socket to the specified server. */
connect(sd, (struct sockaddr *)&sad, sizeof(sad));
if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"connect failed\n");
exit(1);
}
/* Bind a local address to the socket */
bind(sd, (struct sockaddr *)&sad, sizeof(sad));
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Specify size of request queue */
listen(sd, QLEN);
if (listen(sd, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
/* Repeatedly read data from socket and write to user's screen. */
n = recv(sd, buf, sizeof(buf), 0);
while (n > 0) {
int _write(int fd, const void *buffer, unsigned int count);
n = recv(sd, buf, sizeof(buf), 0);
}
/* Main server loop - accept and handle requests */
while (1) {
alen = sizeof(cad);
printf("\nI'm waiting for connections ...");
fflush(stdout);
if ( (sd2=accept(sd, (struct sockaddr *)&cad, &alen)) < 0) {
fprintf(stderr, "accept failed\n");
exit(1);
}
printf("\nI received one connection.\n");
fflush(stdout);
visits++;
sprintf_s(buf,"This server has been contacted %d time%s\n",
visits,visits==1?".":"s.");
send(sd2,buf,strlen(buf),0);
printf("\nI sent the client a string.\n");
fflush(stdout);
closesocket(sd2);
}
/* Close the socket. */
closesocket(sd);
/* Terminate the client program gracefully. */
exit(0);
}
}
If you've made it this far, I thank you for your vigilance. Wish me luck...