void WiFiSDCoopLib::_checkESPAvailableData(const int timeout, String * response, const byte responseType) { char IPDSteps = 0, c; unsigned char ipd; long int time; char endResponse[10]; byte endFlag = 0; byte endLength; byte endPos = 0; String route = ""; switch (responseType) { case WiFiSDCoopLib_RESPONSE_GENERIC: strcpy(endResponse, "OK\r\n"); endLength = 4; break; case WiFiSDCoopLib_RESPONSE_DATA: strcpy(endResponse, "SEND OK\r\n"); endLength = 9; break; case WiFiSDCoopLib_RESPONSE_CIPSEND: strcpy(endResponse, "> "); endLength = 2; break; case WiFiSDCoopLib_RESPONSE_RESET: strcpy(endResponse, "ready\r\n"); endLength = 7; break; case WiFiSDCoopLib_RESPONSE_NO: default: endLength = 0; break; } time = millis() + timeout; while (time > millis()) { while (_dev_available()) { // READING - IPD checks c = _dev_read(); // read the next character. if (IPDSteps == 0 && c != '+' && c != '\n' && c != '\r') { IPDSteps = 10; } if (IPDSteps == 10 && (c == '\n' || c == '\r')) { IPDSteps = 0; } if (response != NULL) { response->concat(c); } // Check if new IPD switch (IPDSteps) { case 0: if (c == '+') { IPDSteps++; } break; case 1: if (c == 'I') { IPDSteps++; } else { IPDSteps = 0; } break; case 2: if (c == 'P') { IPDSteps++; } else { IPDSteps = 0; } break; case 3: if (c == 'D') { IPDSteps++; } else { IPDSteps = 0; } break; case 4: if (c == ',') { IPDSteps++; ipd = 0; } else { IPDSteps = 0; } break; case 5: // Reading IPD channel if (c == ',') { IPDSteps++; } else { ipd = ipd * 10 + c - 48; } break; case 6: // Length, ignored if (c == ':') { IPDSteps++; } break; case 7: // GET, post, etc if (c == ' ') { IPDSteps++; } break; case 8: // Route if (c == ' ') { IPDSteps++; } else { route += c; } break; case 9: // Ignore, request completed case 10: // Ignore, request completed default: break; } // Logic: If end string is reached endFlag is set. Then, decreases to wait some cycles, that should be without data. If data comes means that end is not valid (probably a string identical to end, but no the end itself. // Once arrives 1, and endPos remains 0 (no more data has come) it's a valid end. if(endLength > 0) { if (endPos == endLength - 1 && c == endResponse[endPos]) { endPos = 0; endFlag = 10; } else if (endPos < endLength - 1) { if (c == endResponse[endPos]) { endPos++; } else { endPos = 0; endFlag = 0; } } else { endPos = 0; endFlag = 0; } // if endPos becomes 0, check again to don't miss a end string start. if (endPos == 0 && c == endResponse[endPos]) { endPos++; } } // End request end checks } if (endFlag > 1) { endFlag--; } if (endLength > 0 && endFlag == 1 && endPos == 0) { // valid END return; } if (IPDSteps == 9) { // Request fond, check routes IPDStruct * last = IPDs; bool found = false; while (last != NULL) { if (last->mode == 4) {// 4 Default route found = true; } else if (strlen(last->route) <= route.length()) { switch (last->mode) { case 3:// 3 found in any position found = route.indexOf(last->route) >= 0; break; case 2:// 2 ends with found = route.endsWith(last->route); break; case 1:// 1 starts with found = route.startsWith(last->route); break; case 0:// 0 same string default: found = route.equals(last->route); break; } } if (found) { last->fp(route, ipd); _sendCloseIPD(ipd); return; } last = (IPDStruct *) last->next; } sendDataByIPD(ipd, F("404 - Not found")); _sendCloseIPD(ipd); } // IPD found, routes checks end } // End timeout while }
static __inline size_t _readbinary(void* a, size_t n, FILE* str) { /* reads in data from a stream into the caller's namespace ** using binary mode (assumes that n, the number of memory locations ** to be read, is positive) - returns the number of words read ** ** there is no difference in the way that fread reads a file in text ** mode or in binary mode when (BYTES_PER_WORD==1). ** ** any data that is in the I/O buffer is read first - if the fread ** request is not satisfied then either further data is read from ** the file directly into the caller's namespace (but only if the ** amount of data exceeds the size of the I/O buffer), or the buffer ** is refilled. ** ** note that some care is required because this procedure short-cuts ** the usual mechanisms. ** ** parameters: ** a - data is read into this array ** n - amount of data (still) needed (in memory units) ** str - ptr to the FILE table for the stream */ size_t buflen; /* the size of the I/O buffer */ int m; /* how much data available (in memory units) */ int c = 0; /* how much data has been read (in memory units) */ int r; /* result from a read operation */ int w; /* number of memory units read */ do { m = str->_Rend - str->_Next; if (m > 0) { /* there is data in the input buffer */ if (m > n) m = n; /* take what we want if there is more than we need */ memcpy(((unsigned char *) a) + c, (unsigned char *) str->_Next,m); str->_Next += m; if (m == n) return c+n; /* still need data - there is an I/O buffer but it is empty */ n -= m; /* decrement the amount still needed */ c += m; /* increment the amount read so far */ } /* read some data (PS: there might be no I/O buffer) */ buflen = (str->bufadr) ? (str->_Bend - str->bufadr) : BUFSIZ; if (n > buflen) { /* optimize - bypass buffer - read directly into array */ r = _dev_read(str->fileID,((char *) a) + c,n * BYTES_PER_WORD); if (r < 0) { str->_Mode |= M_ERROR; return 0; } w = (r + (BYTES_PER_WORD - 1)) / BYTES_PER_WORD; if (n != w) { str->_Mode = (str->_Mode & ~M_LAST_READ) | M_EOF; } else { #if (BYTES_PER_WORD != 1) unsigned char *const ptr = &((unsigned char *)a)[(r-1)/BYTES_PER_WORD]; int rem = r & (BYTES_PER_WORD-1); if (rem != 0) { *ptr &= (UCHAR_MAX >> ((BYTES_PER_WORD - rem) * 8)); // organize padding of last incomplete word } #endif } return c + w; }