Handler et parseur simple pour un fichier XML pour le projet télécommande par iPhone ou iPod, remplace un tag par la valeur de la variable entière. Très perfectible.
Diff: FSWagoHandler.cpp
- Revision:
- 0:2b2fce21fd82
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FSWagoHandler.cpp Fri Oct 29 21:48:27 2010 +0000 @@ -0,0 +1,248 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +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. + +Copyright (c) 2010 Pautex Jean-Francois +Realise l'interface wagoml de style d'appel : http://ip/wagoml/fichier.xml +Remplace le texte dans les balises de type : "@MnREAD" par une valeur numerique +## PREMIERE PUBLICATION +- la longueur de fichier xml n'est pas modifiable. +- les variables sont limités a M1, M2, M3, M4, et M5 + +*/ + +#include "FSWagoHandler.h" + +// #define __DEBUG +#include "dbg/dbg.h" + +#define CHUNK_SIZE 1024 + +#define DEFAULT_PAGE "/index.xml" +extern int M0,M1,M2,M3,M4,M5; // val de variable en Entier 0.. 32768 + +FSWagoHandler::FSWagoHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : HTTPRequestHandler(rootPath, path, pTCPSocket), m_err404(false) {} + +FSWagoHandler::~FSWagoHandler() { + if (m_fp) + fclose(m_fp); + DBG("\r\nHandler destroyed\r\n"); +} + +//static init +map<string,string> FSWagoHandler::m_lFsPath = map<string,string>(); + +void FSWagoHandler::mount(const string& fsPath, const string& rootPath) { + m_lFsPath[rootPath]=fsPath; +} + +void FSWagoHandler::doGet() { + DBG("\r\nIn FSWagoHandler::doGet() - rootPath=%s, path=%s\r\n", rootPath().c_str(), path().c_str()); + //FIXME: Translate path to local/path + string checkedRootPath = rootPath(); + if (checkedRootPath.empty()) + checkedRootPath="/"; + string filePath = m_lFsPath[checkedRootPath]; + if (path().size() > 1) { + filePath += path(); + // filePath += DEFAULT_PAGE; // test + } else { + filePath += DEFAULT_PAGE; + } + + DBG("Trying to open %s\r\n", filePath.c_str()); + + m_fp = fopen(filePath.c_str(), "r"); //FIXME: if null, error 404 + + + + if (!m_fp) { // all not ok erre lecture + m_err404 = true; + setErrCode(404); + const char* msg = "File not found."; + setContentLen(strlen(msg)); + respHeaders()["Content-Type"] = "text/xml"; + respHeaders()["Connection"] = "close"; + writeData(msg,strlen(msg)); //Only send header + DBG("\r\nExit FSWagoHandler::doGet() w Error 404\r\n"); + return; + } + + //Seek EOF to get length + fseek(m_fp, 0, SEEK_END); + setContentLen( ftell(m_fp) ); + fseek(m_fp, 0, SEEK_SET); //Goto SOF + + respHeaders()["Connection"] = "close"; + onWriteable(); + DBG("\r\nExit SimpleHandler::doGet()\r\n"); +} + +void FSWagoHandler::doPost() { + +} + +void FSWagoHandler::doHead() { + +} + +void FSWagoHandler::onReadable() { //Data has been read + +} + +void FSWagoHandler::onWriteable() { //Data has been written & buf is free + DBG("\r\nFSHandler::onWriteable() event\r\n"); + if (m_err404) { + //Error has been served, now exit + close(); + return; + } + + // buffer de 1024 bytes + static char rBuf[CHUNK_SIZE]; // vuffer allong� on va en ajouter + + while (true) { + int len = fread(rBuf, 1, CHUNK_SIZE, m_fp); + len = decode(rBuf,len); + + if (len>0) { + int writtenLen = writeData(rBuf, len); // sortie du packet 128 byt + if (writtenLen < 0) { //Socket error + DBG("FSWagoHandler: Socket error %d\n", writtenLen); + if (writtenLen == TCPSOCKET_MEM) { + fseek(m_fp, -len, SEEK_CUR); + return; //Wait for the queued TCP segments to be transmitted + } else { + //This is a critical error + close(); + return; + } + } else if (writtenLen < len) { //Short write, socket's buffer is full + fseek(m_fp, writtenLen - len, SEEK_CUR); + return; + } + } else { + close(); //Data written, we can close the connection + return; + } + } +} + +void FSWagoHandler::onClose() { //Connection is closing + if (m_fp) + fclose(m_fp); +} +// --------------------------------------------------------------------------- +// dans le fichier xml cible recherche et remplacementt simple ----------- +// +// cherche variable @M0READ @M1READ etc et remplace par la valeur de M0, M1 etc... +// on est dans la balise <IW>@M0READ</IW> du fichier wagoml en general, len est inutilisé +// car il n'est pas modifié. +int FSWagoHandler::decode(char* rBuf, int len) { + // DBG("\r\nFSWagoHandler: decode %d\r\n", len); + int index; + char str[16]; + + index = indexOfChar(rBuf,len,'@'); // trouve @ debut de la memoire reference @M0READ par exemple + + while ( (index = indexOfChar(rBuf,len,'@')) > 0 ) { + if ( rBuf[index+6] == 'D') { // operation de lecture de valeur + // retrouve data pour <IW> + int valeur; + char indchar = rBuf[index+2]; + switch (indchar) { + case '0' : + valeur = M0; + break; + case '1' : + valeur = M1; + break; + case '2' : + valeur = M2; + break; + case '3' : + valeur = M3; + break; + case '4' : + valeur = M4; + break; + case '5' : + valeur = M5; + break; + default : + valeur = 0; + } + + // lecture de quel valeur ici il est complet + rBuf[index] = '+'; // ajoute + optionnel pour test + rBuf[index+6] = ' '; // efface le "D" + + // copie la valeur a la place de MXREAD + sprintf(str,"%d", valeur ); + rBuf[index+1] = str[0]; + + if ( valeur >= 10) rBuf[index+2] = str[1]; + else rBuf[index+2] = ' '; + if ( valeur >= 100) rBuf[index+3] = str[2]; + else rBuf[index+3] = ' '; + if ( valeur >= 1000) rBuf[index+4] = str[3]; + else rBuf[index+4] = ' '; + if ( valeur >= 10000) rBuf[index+5] = str[4]; + else rBuf[index+5] = ' '; + } + } + return len; +} + +// index de caractere ds buf trouve x, redonne la position du premier trouve +int FSWagoHandler::indexOfChar(char* rBuf, int len, char x) { + int pos = -1, i; + for (i=0; i<len; i++) { + if ( rBuf[i] == x ) { + pos = i; + break; + } + } + return pos; +} + +// remplace une chaine - inutilisé +int FSWagoHandler::remplaceCharAtIndex(char* rBuf, int len, int index, char x) { + rBuf[index] = x; + return len; +} + +// remplace une chaine (non utilise pour le moment) +int FSWagoHandler::insertCharsAtIndex(char* rBuf, int len, int index, char* x, int lenx) { + int i; + // fait une place en partant de la fin + for (i=len+lenx-1; i >= index+lenx; i--) { + rBuf[i] = rBuf[i-lenx]; + } + // recopie chaine entrante ds le etrou + for (i=0; i<lenx; i++) { + rBuf[index+i] = x[i]; + } + return len + lenx; +} + + +// -------------------------------- \ No newline at end of file