void ESP8266WebServer::handleClient() { WiFiClient client = _server.available(); if (!client) { return; } #ifdef DEBUG Serial.println("New client"); #endif // Wait for data from client to become available while(client.connected() && !client.available()){ delay(1); } // Read the first line of HTTP request String req = client.readStringUntil('\r'); client.readStringUntil('\n'); HTTPMethod method = HTTP_GET; if (req.startsWith("POST")) { method = HTTP_POST; } // First line of HTTP request looks like "GET /path HTTP/1.1" // Retrieve the "/path" part by finding the spaces int addr_start = req.indexOf(' '); int addr_end = req.indexOf(' ', addr_start + 1); if (addr_start == -1 || addr_end == -1) { #ifdef DEBUG Serial.print("Invalid request: "); Serial.println(req); #endif return; } req = req.substring(addr_start + 1, addr_end); String formData; if (method == HTTP_POST) { int contentLength = -1; int headerCount = 0; while(headerCount < 1024) { // there shouldn't be that much really String line = client.readStringUntil('\r'); client.readStringUntil('\n'); if (line.length() > 0) { // this is a header ++headerCount; if (contentLength < 0 && line.startsWith("Content-Length")) { // get content length from the header int valuePos = line.indexOf(' ', 14); if (valuePos > 0) { String valueStr = line.substring(valuePos+1); contentLength = valueStr.toInt(); #ifdef DEBUG Serial.print("Content-Length: "); Serial.println(contentLength); #endif } } } else { break; } } #ifdef DEBUG Serial.print("headerCount="); Serial.println(headerCount); #endif if (contentLength >= 0) { formData = ""; int n = 0; // timeout counter while (formData.length() < contentLength && ++n < 3) formData += client.readString(); } else { formData = client.readStringUntil('\r'); // will return after timing out once } } else if (method == HTTP_GET) { int args_start = req.indexOf('?'); if (args_start != -1) { formData = req.substring(args_start + 1); req = req.substring(0, args_start); } } client.flush(); #ifdef DEBUG Serial.print("Request: "); Serial.println(req); Serial.print("Args: "); Serial.println(formData); #endif _parseArguments(formData); _handleRequest(client, req, method); }
// Process HTTP requests -- just call it inside the loop() function void WebConfig::ProcessHTTP() { // Accept any new web connection WiFiClient httpClient = pHttpServer->available(); if (!httpClient) return; // Read the entire request String req = httpClient.readString(); httpClient.flush(); // after some time, do not open the web interface anymore. //if (millis() - startMillis > 2*60000) return; // response header String s; if (strlen(webLogin) > 0 || strlen(webPassword) > 0) { int authPos = req.indexOf("Authorization: Basic"); if (authPos == -1) { // request authentication s = "HTTP/1.0 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"" + String(apName) + "\"\r\n\r\n"; s += "<h1><b>ACCESS DENIED</b></h1>"; httpClient.write(s.c_str(), s.length()); httpClient.flush(); return; } // there is authentication info, check it String authInfo = req.substring(authPos + 21); int endLinePos = authInfo.indexOf("\r"); if (endLinePos == -1) { httpClient.print("Malformed request."); httpClient.stop(); return; } authInfo = authInfo.substring(0, endLinePos); if (strncmp(base64Auth, authInfo.c_str(), 64)) { s = "<h1><b>ACCESS DENIED</b></h1>"; httpClient.write(s.c_str(), s.length()); httpClient.flush(); return; } } byte mac[6]; WiFi.macAddress(mac); String m = String(mac[0],HEX) + ":" + String(mac[1],HEX) + ":" + String(mac[2],HEX) + ":" + String(mac[3],HEX) + ":" + String(mac[4],HEX) + ":" + String(mac[5],HEX); // // generate HTTP response // // authentication succeeded, proceed normally s = "HTTP/1.1 200 OK\r\n"; s += "Content-Type: text/html\r\n\r\n"; s += "<!DOCTYPE HTML>\r\n<html><body>\r\n"; // If there are parms, update variables and save settings bool updated = ProcessParms(req); if (updated) { s += "Parameters have been updated and microcontroller will restart.<br><br>\r\n"; } // javascript to save configuration s += "<script>\r\n"; s += "function save()\r\n"; s += "{\r\n"; s += "var webPort = document.getElementById('web_port').value;\r\n"; s += "var webLogin = document.getElementById('web_login').value;\r\n"; s += "var webPassword = document.getElementById('web_pass').value;\r\n"; s += "var webPassword2 = document.getElementById('web_pass2').value;\r\n"; s += "var modeap = document.getElementById('modeap').checked;\r\n"; s += "if (modeap) isAP = true; else isAP = false;\r\n"; s += "var apName = document.getElementById('ap_ssid').value;\r\n"; s += "var apPassword = document.getElementById('ap_pass').value;\r\n"; s += "var apPassword2 = document.getElementById('ap_pass2').value;\r\n"; s += "var apChannel = document.getElementById('apChannel').value;\r\n"; s += "var ssid = document.getElementById('ssid').value;\r\n"; s += "var password = document.getElementById('pass').value;\r\n"; s += "var password2 = document.getElementById('pass2').value;\r\n"; s += "var udpPort = document.getElementById('udpPort').value;\r\n"; s += "var tcpPort = document.getElementById('tcpPort').value;\r\n"; s += "if (webPassword != webPassword2) { alert('WEB passwords dont match'); return; }\r\n"; s += "if (apPassword != apPassword2) { alert('AP passwords dont match'); return; }\r\n"; s += "if (password != password2) { alert('Router passwords dont match'); return; }\r\n"; s += "window.location.search=webPort + '&' + webLogin + '&' + webPassword + '&' + btoa(webLogin+':'+webPassword) + '&' + (isAP?'1':'0') + '&' + apName + '&' + apPassword + '&' + apChannel + '&' + ssid + '&' + password + '&' + udpPort + '&' + tcpPort;\r\n"; s += "}\r\n"; s += "</script>\r\n"; // write first part of response httpClient.write(s.c_str(), s.length()); // title and mac address s = "<b>" + String(name) + "</b><br>\r\n"; s += "MAC: " + m + "<br>\r\n"; // web interface configuration s += "<table border=1>\r\n"; s += "<tr><td colspan=2 bgcolor=#E0E0E0><b>WEB INTERFACE</b></td></tr>\r\n"; s += "<tr><td>Port</td><td><input type=text id='web_port' value='" + String(webPort) + "'></td></tr>\r\n"; s += "<tr><td>Login</td><td><input type=text id='web_login' value='" + String(webLogin) + "'></td></tr>\r\n"; s += "<tr><td>Password</td><td><input type=password id='web_pass' value='" + String(webPassword) + "'></td></tr>\r\n"; s += "<tr><td>Pass Confirm</td><td><input type=password id='web_pass2' value='" + String(webPassword) + "'></td></tr>\r\n"; s += "</table>\r\n"; // ap configuration s += "<table border=1>\r\n"; s += "<tr><td colspan=2 bgcolor=#E0E0E0><b>ACCESS POINT</b></td></tr>\r\n"; s += "<tr><td>Mode</td><td><input type=radio id='modeap' name='mode' value='ap'" + (isAP?String(" checked"):String("")) + ">Access Point</td></tr>\r\n"; s += "<tr><td>Channel</td><td><select id='apChannel'>"; for (byte c=1; c<14; c++) s += "<option value='" + String(c) + "'" + (c==apChannel?String(" selected"):String("")) + ">" + String(c) + "</option>"; s += "</select></td></tr>\r\n"; s += "<tr><td>SSID</td><td><input type=text id='ap_ssid' value='" + String(apName) + "'></td></tr>\r\n"; s += "<tr><td>Password</td><td><input type=password id='ap_pass' value='" + String(apPassword) + "'></td></tr>\r\n"; s += "<tr><td>Pass Confirm</td><td><input type=password id='ap_pass2' value='" + String(apPassword) + "'></td></tr>\r\n"; s += "</table>\r\n"; // station configuration s += "<table border=1>\r\n"; s += "<tr><td colspan=2 bgcolor=#E0E0E0><b>STATION</b></td></tr>\r\n"; s += "<tr><td>Mode</td><td><input type=radio id='modest' name='mode' value='station'" + (isAP?String(""):String(" checked")) + ">Station</td></tr>\r\n"; s += "<tr><td>SSID</td><td><input type=text id='ssid' value='" + String(ssid) + "'></td></tr>\r\n"; s += "<tr><td>Password</td><td><input type=password id='pass' value='" + String(password) + "'></td></tr>\r\n"; s += "<tr><td>Pass Confirm</td><td><input type=password id='pass2' value='" + String(password) + "'></td></tr>\r\n"; s += "</table>\r\n"; // udp/tcp ports configuration s += "<table border=1>\r\n"; s += "<tr><td colspan=2 bgcolor=#E0E0E0><b>UDP|TCP LISTENERS</b></td></tr>\r\n"; s += "<tr><td>UDP Port</td><td><input type=text id='udpPort' value='" + String(udpPort) + "'></td></tr>\r\n"; s += "<tr><td>TCP Port</td><td><input type=text id='tcpPort' value='" + String(tcpPort) + "'></td></tr>\r\n"; s += "</table>\r\n"; // save button s += "<input type=button value='Save and Reset' onClick='save()'>\r\n"; // end of HTTP s += "</body></html>\r\n"; // write second part of response httpClient.write(s.c_str(), s.length()); httpClient.flush(); if (updated) { // give some time delay(2000); // reset the microcontroller Reset(); } }
//////////////////////////////////// // Scrape UTC Time from server //////////////////////////////////// char* updateCurTime(void) { static int timeout_busy=0; int ipos; timeout_busy=0; //reset const char* timeServer = "aws.amazon.com"; // send a bad header on purpose, so we get a 400 with a DATE: timestamp const char* timeServerGet = "GET example.com/ HTTP/1.1"; String utctime; String GmtDate; static char dateStamp[20]; static char chBuf[200]; char utctimeraw[80]; char* dpos; WiFiClient client; if (client.connect(timeServer, 80)) { //Send Request client.println(timeServerGet); client.println(); while((!client.available())&&(timeout_busy++<5000)){ // Wait until the client sends some data delay(1); } // kill client if timeout if(timeout_busy>=5000) { client.flush(); client.stop(); Serial.println("timeout receiving timeserver data\n"); return dateStamp; } // read the http GET Response String req2 = client.readString(); // Serial.println(""); // Serial.println(""); // Serial.print(req2); // Serial.println(""); // Serial.println(""); // close connection delay(1); client.flush(); client.stop(); ipos = req2.indexOf("Date:"); if(ipos>0) { GmtDate = req2.substring(ipos,ipos+35); // Serial.println(GmtDate); utctime = GmtDate.substring(18,22) + getMonth(GmtDate.substring(14,17)) + GmtDate.substring(11,13) + GmtDate.substring(23,25) + GmtDate.substring(26,28) + GmtDate.substring(29,31); // Serial.println(utctime.substring(0,14)); utctime.substring(0,14).toCharArray(dateStamp, 20); } } else { Serial.println("did not connect to timeserver\n"); } timeout_busy=0; // reset timeout return dateStamp; // Return latest or last good dateStamp }