/*** GCMD::ACTION ComposeHTMLTerminatePage(CLIENTINFO * pClientInfo) * * Parameters: * pClientInfo - the client info representing this connection and web page * * Return Values: * GCMD::ACTION - GCMD::CONTINUE, just return with no outside action * - GCMD::READ, non-blocking read of input data into the rgbIn buffer appended to the end of cbRead * - GCMD::GETLINE, blocking read until a line of input is read or until the rgbIn buffer is full, always the line starts at the beginnig of the rgbIn * - GCMD::WRITE, loop writing until all cbWrite bytes are written from the pbOut buffer * - GCMD::DONE, we are done processing and the connection can be closed * * Description: * * Renders the server terminate HTML page * * ------------------------------------------------------------ */ GCMD::ACTION ComposeHTMLTerminatePage(CLIENTINFO * pClientInfo) { GCMD::ACTION retCMD = GCMD::WRITE; switch(pClientInfo->htmlState) { case HTTPSTART: xil_printf("Terminate Request Detected\r\n"); pClientInfo->cbWrite = BuildHTTPOKStr(true, sizeof(szTerminate)-1, ".htm", (char *) pClientInfo->rgbOut, sizeof(pClientInfo->rgbOut)); pClientInfo->pbOut = pClientInfo->rgbOut; pClientInfo->htmlState = WRITECONTENT; break; case WRITECONTENT: pClientInfo->pbOut = (const byte *) szTerminate; pClientInfo->cbWrite = sizeof(szTerminate)-1; pClientInfo->htmlState = DONE; break; case DONE: default: pClientInfo->cbWrite = 0; retCMD = GCMD::TERMINATE; break; } return(retCMD); }
/*** GCMD::ACTION ComposeHTMLSDPage(CLIENTINFO * pClientInfo) * * Parameters: * pClientInfo - the client info representing this connection and web page * * Return Values: * GCMD::ACTION - GCMD::CONTINUE, just return with no outside action * - GCMD::READ, non-blocking read of input data into the rgbIn buffer appended to the end of cbRead * - GCMD::GETLINE, blocking read until a line of input is read or until the rgbIn buffer is full, always the line starts at the beginnig of the rgbIn * - GCMD::WRITE, loop writing until all cbWrite bytes are written from the pbOut buffer * - GCMD::DONE, we are done processing and the connection can be closed * * Description: * * This renders a page off of the SD filesystem. Pages of type * .htm, .html, .jpeg, .png, .txt and more may be rendered * The file extension on the filename determine the MIME type * returned to the client. * * ------------------------------------------------------------ */ GCMD::ACTION ComposeHTMLSDPage(CLIENTINFO * pClientInfo) { char * pFileNameEnd = NULL; GCMD::ACTION retCMD = GCMD::CONTINUE; switch(pClientInfo->htmlState) { case HTTPSTART: if(pClientMutex != NULL || (sdLockId = lockSD()) == SDUNLOCKED) { break; } pClientMutex = pClientInfo; Serial.println("Read an HTML page off of the SD card"); Serial.print("Entering Client ID: 0x"); Serial.println((uint32_t) pClientMutex, HEX); pClientInfo->htmlState = PARSEFILENAME; retCMD = GCMD::GETLINE; break; case PARSEFILENAME: // the assumption is that the file name will be on the first line of the command // there is a bunch of other stuff on the line we don't care about, but it is at the // end of the line. Serial.println((char *) pClientInfo->rgbIn); // find the begining of the file name szFileName = strstr((const char *) pClientInfo->rgbIn, szGET); if(szFileName == NULL) { pClientInfo->htmlState = JMPFILENOTFOUND; break; } szFileName += sizeof(szGET) - 1; // find the end of the file name pFileNameEnd = strstr(szFileName, szEndOfURL); if(pFileNameEnd == NULL) { pClientInfo->htmlState = JMPFILENOTFOUND; break; } else if(pFileNameEnd == szFileName) { szFileName = szDefaultPage; } else { *pFileNameEnd = '\0'; } Serial.print("SD FileName:"); Serial.println(szFileName); if(dFile.fsopen(szFileName, FA_READ) == FR_OK) { Serial.print("HTML page:"); Serial.print(szFileName); Serial.println(" exists!"); pClientInfo->htmlState = BUILDHTTP; } else { Serial.print("Unable to find HTML page:"); Serial.println(szFileName); pClientInfo->htmlState = JMPFILENOTFOUND; } break; // We need to build the HTTP directive case BUILDHTTP: if(dFile && (dFile.fslseek(0) == FR_OK)) { pClientInfo->cbWrite = BuildHTTPOKStr(false, dFile.fssize(), szFileName, (char *) pClientInfo->rgbOut, sizeof(pClientInfo->rgbOut)); if(pClientInfo->cbWrite > 0) { pClientInfo->pbOut = pClientInfo->rgbOut; retCMD = GCMD::WRITE; pClientInfo->htmlState = SENDFILE; cbSent = 0; tStart = millis(); Serial.print("Writing file:"); Serial.println(szFileName); } else { Serial.print("Unable to build HTTP directive for file:"); Serial.println(szFileName); pClientInfo->htmlState = JMPFILENOTFOUND; } } else { Serial.print("Unable to open HTML page:"); Serial.println(szFileName); pClientInfo->htmlState = JMPFILENOTFOUND; } break; // Send the file case SENDFILE: { uint32_t cbT = 0; if((cbT = SDRead(dFile, pClientInfo->rgbOut, sizeof(pClientInfo->rgbOut))) > 0) { cbSent += cbT; pClientInfo->pbOut = pClientInfo->rgbOut; pClientInfo->cbWrite = cbT; tStart = millis(); retCMD = GCMD::WRITE; } else if(cbSent == dFile.fssize()) { pClientInfo->htmlState = EXIT; } else if((millis() - tStart) > SDREADTIMEOUT) { pClientInfo->htmlState = HTTPTIMEOUT; } } break; case EXIT: Serial.println("Wrote page cleanly"); pClientInfo->htmlState = HTTPDISCONNECT; break; case JMPFILENOTFOUND: Serial.println("Jumping to HTTP File Not Found page"); if(isMySD(sdLockId)) { if(dFile) { dFile.fsclose(); } sdLockId = unlockSD(sdLockId); } pClientMutex = NULL; return(JumpToComposeHTMLPage(pClientInfo, ComposeHTTP404Error)); break; case HTTPTIMEOUT: Serial.println("Timeout error occured, closing the session"); // fall thru to close case HTTPDISCONNECT: if(pClientMutex == pClientInfo) { Serial.print("Closing Client ID: 0x"); Serial.println((uint32_t) pClientMutex, HEX); if(isMySD(sdLockId)) { if(dFile) { dFile.fsclose(); } sdLockId = unlockSD(sdLockId); } pClientMutex = NULL; } // fall thru Done case DONE: default: pClientInfo->cbWrite = 0; retCMD = GCMD::DONE; break; } return(retCMD); }
/*** GCMD::ACTION ComposeHTMLGetIO(CLIENTINFO * pClientInfo) * * Parameters: * pClientInfo - the client info representing this connection and web page * * Return Values: * GCMD::ACTION - GCMD::CONTINUE, just return with no outside action * - GCMD::READ, non-blocking read of input data into the rgbIn buffer appended to the end of cbRead * - GCMD::GETLINE, blocking read until a line of input is read or until the rgbIn buffer is full, always the line starts at the beginnig of the rgbIn * - GCMD::WRITE, loop writing until all cbWrite bytes are written from the pbOut buffer * - GCMD::DONE, we are done processing and the connection can be closed * * Description: * * This renders a page of the LEDs, BTNs, or SWTs on the device * It reads a template page from the SD card, puts it into a temp * RAM buffer, and then updates the template with acutal values * ------------------------------------------------------------ */ GCMD::ACTION ComposeHTMLGetIO(CLIENTINFO * pClientInfo) { char * pFileNameEnd = NULL; GCMD::ACTION retCMD = GCMD::CONTINUE; switch(pClientInfo->htmlState) { case HTTPSTART: // serialize so we only do this page once at a time // this protects the szPageBuffer if(pClientMutex != NULL) { break; } pClientMutex = pClientInfo; Serial.println("Get IO Page Detected"); Serial.print("Entering Client ID: 0x"); Serial.println((uint32_t) pClientMutex, HEX); pClientInfo->htmlState = READTEMPLATE; break; // Read the template htm case READTEMPLATE: // We want to serialize usage to the SD card if((sdLockId = lockSD()) == SDUNLOCKED) { break; } // open the templeate file if((fileSD = SD.open(szIOPage, FILE_READ)) && fileSD.seek(0) ) { // because we have the SD file data now, build the HTTP header in the output temp buffer // we will only use this if all goes well. // this will be held for 2 states cbFile = fileSD.size(); pClientInfo->cbWrite = BuildHTTPOKStr(false, cbFile, szIOPage, (char *) pClientInfo->rgbOut, sizeof(pClientInfo->rgbOut)); // since szIOPage is a template .htm, this better always be true! if( 0 < cbFile && cbFile < sizeof(szPageBuffer) && SDRead(fileSD, (uint8_t *) szPageBuffer, cbFile) == cbFile ) { // That Read could have takin some time, so lets release and pick up // on another state szPageBuffer[cbFile] = '\0'; iReplace = 0; pchLast = szPageBuffer; pClientInfo->htmlState = REPLACE; } // not good, not expected either else { Serial.print("Unable to build HTTP directive for file:"); Serial.println(szIOPage); Serial.print("Sizeof "); Serial.print(szIOPage); Serial.print(" is "); Serial.print(cbFile, DEC); Serial.println(" bytes"); Serial.print("Sizeof page buffer is"); Serial.print(sizeof(szPageBuffer), DEC); Serial.println(" bytes"); pClientInfo->htmlState = JMPFILENOTFOUND; } } // something is wrong with the SD card; which happens :-( else { Serial.print("Unable to open HTML page:"); Serial.println(szIOPage); pClientInfo->htmlState = JMPFILENOTFOUND; } // no matter what, were are done with the SD Card fileSD.close(); sdLockId = unlockSD(sdLockId); break; case REPLACE: // do our replacentments one string at a time. if(iReplace < cReplacementStrings) { if((pchLast = strstr(pchLast, szReplaceStr)) == NULL) { // oh this is not good, something is wrong with the template file Serial.print("Unable able to find template replacemnt on index "); Serial.print(iReplace, DEC); Serial.print(" in template file "); Serial.println(szIOPage); pClientInfo->htmlState = JMPFILENOTFOUND; } else { bool isOn = digitalRead(rgReplacePins[iReplace]); if(iReplace < HTTPCIO) { if(isOn) { memcpy(pchLast, szON, sizeof(szON)-1); } else { memcpy(pchLast, szOFF, sizeof(szOFF)-1); } } else if((iReplace - HTTPCIO) < HTTPCLED) { if(isOn) { memcpy(pchLast, szChecked, sizeof(szChecked)-1); } else { memcpy(pchLast, szUnChecked, sizeof(szUnChecked)-1); } } // do the next replacement string. iReplace++; } } // time to start writing stuff out, first the HTTP header that has // been sitting in pClientInfo->rgbOut else { pClientInfo->pbOut = pClientInfo->rgbOut; retCMD = GCMD::WRITE; pClientInfo->htmlState = SENDFILE; } break; // Send the file case SENDFILE: pClientInfo->cbWrite = cbFile; pClientInfo->pbOut = (byte *) szPageBuffer; retCMD = GCMD::WRITE; pClientInfo->htmlState = EXIT; break; case EXIT: Serial.println("Wrote page cleanly"); pClientInfo->htmlState = HTTPDISCONNECT; break; case JMPFILENOTFOUND: Serial.println("Jumping to HTTP File Not Found page"); pClientMutex = NULL; return(JumpToComposeHTMLPage(pClientInfo, ComposeHTTP404Error)); break; case HTTPTIMEOUT: Serial.println("Timeout error occured, closing the session"); // fall thru to close case HTTPDISCONNECT: if(pClientMutex == pClientInfo) { Serial.print("Closing Client ID: 0x"); Serial.println((uint32_t) pClientMutex, HEX); pClientMutex = NULL; } // fall thru Done case DONE: default: pClientInfo->cbWrite = 0; retCMD = GCMD::DONE; break; } return(retCMD); }