Christian Gulde / ModBusTCP

Fork of HTTPD by AMETEK Powervar

Files at this revision

API Documentation at this revision

Comitter:
gulchi
Date:
Fri Jun 30 08:17:01 2017 +0000
Parent:
2:fcd20e2cd110
Child:
4:41ee166a0e6c
Commit message:
Working ModBusTCP Interface with Mbed-os

Changed in this revision

HTTPD_req.cpp Show diff for this revision Revisions of this file
HTTPD_util.cpp Show diff for this revision Revisions of this file
HTTPD_ws.cpp Show diff for this revision Revisions of this file
ModBus-Req.cpp Show annotated file Show diff for this revision Revisions of this file
ModBus-TCP.cpp Show annotated file Show diff for this revision Revisions of this file
ModBus-TCP.h Show annotated file Show diff for this revision Revisions of this file
ModBus_util.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/HTTPD_req.cpp	Thu Jun 29 10:17:29 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/* Copyright (C) 2013 Hiroshi Suga, MIT License
- *
- * 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.
- */
-
-#include "HTTPD.h"
-
-
-int HTTPD::httpdFile (int id, char *dir) {
-    FILE *fp;
-    int i, len;
-    char buf[HTTPD_BUF_SIZE];
-    char file[HTTPD_CMD_SIZE];
-
-    INFO("httpdFile %d %s", id, dir);
-
-    strcpy(file, dir);
-    strcat(file, _state[id].filename);
-    if (file[strlen(file) - 1] == '/') {
-        strcat(file, "index.html");
-    }
-    DBG("file: %s\r\n", file);
-
-    fp = fopen(file, "r");
-    if (fp) {
-        strcpy(buf, "HTTP/1.1 200 OK\r\n");
-        _state[id].client->send(buf, strlen(buf));
-        {
-            // file size
-            i = ftell(fp);
-            fseek(fp, 0, SEEK_END);
-            len = ftell(fp);
-            fseek(fp, i, SEEK_SET);
-        }
-
-        strcpy(buf, "Server: GSwifi httpd\r\n");
-        _state[id].client->send(buf, strlen(buf));
-        if (_state[id].keepalive) {
-            strcpy(buf, "Connection: Keep-Alive\r\n");
-        } else {
-            strcpy(buf, "Connection: close\r\n");
-        }
-        _state[id].client->send(buf, strlen(buf));
-        sprintf(buf, "Content-Type: %s\r\n", mimetype(file));
-        _state[id].client->send(buf, strlen(buf));
-        sprintf(buf, "Content-Length: %d\r\n\r\n", len);
-        _state[id].client->send(buf, strlen(buf));
-
-        for (;;) {
-            i = fread(buf, sizeof(char), sizeof(buf), fp);
-            if (i <= 0) break;
-            _state[id].client->send(buf, i);
-#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
-            if (feof(fp)) break;
-#endif
-        }
-        fclose(fp);
-        return 0;
-    }
-    
-    httpdError(id, 404);
-    return -1;
-}
-
-void HTTPD::httpdError (int id, int err) {
-    char buf[HTTPD_CMD_SIZE], msg[30];
-    
-    switch (err) {
-    case 400:
-        strcpy(msg, "Bad Request");
-        break;
-    case 403:
-        strcpy(msg, "Forbidden");
-        break;
-    case 404:
-        strcpy(msg, "Not Found");
-        break;
-    case 500:
-    default:
-        strcpy(msg, "Internal Server Error");
-        break;
-    }
-    DBG("httpd error: %d %d %s\r\n", id, err, msg);
-    
-    sprintf(buf, "HTTP/1.1 %d %s\r\n", err, msg);
-    _state[id].client->send(buf, strlen(buf));
-    strcpy(buf, "Content-Type: text/html\r\n\r\n");
-    _state[id].client->send(buf, strlen(buf));
-
-    sprintf(buf, "<html><head><title>%d %s</title></head>\r\n", err, msg);
-    _state[id].client->send(buf, strlen(buf));
-    sprintf(buf, "<body><h1>%s</h1></body></html>\r\n", msg);
-    _state[id].client->send(buf, strlen(buf));
-    wait_ms(100);
-    _state[id].client->close();
-    //WARN("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]);
-    //WARN("%s %s %d %d -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, err);
-}
-
-void HTTPD::recvData (int id, char c) {
-
-    switch (_state[id].mode) {
-    case MODE_REQUEST:
-        if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
-            _state[id].buf->flush();
-            _state[id].buf->queue(c);
-            _state[id].mode = MODE_REQSTR;
-        } else {
-            _state[id].buf->flush();
-        }
-        break;
-    case MODE_REQSTR:
-        switch (c) {
-        case 0:
-            break;
-        case 0x0a: // LF
-        case 0x0d: // CR
-            if (parseRequest(id)) {
-                _state[id].mode = MODE_REQSTR;
-            } else {
-                _state[id].mode = MODE_HEADER;
-            }
-            _state[id].enter = 0;
-            break;
-        default:
-            _state[id].buf->queue(c);
-            break;
-        }
-        break;
-    case MODE_HEADER:
-        switch (c) {
-        case 0:
-            break;
-        case 0x0a: // LF
-        case 0x0d: // CR
-            if (_state[id].buf->available() == 0) {
-                if ((_state[id].enter == 0x0d && c == 0x0a) || (_state[id].enter == 0x0a && c == 0x0a)) {
-                    _state[id].buf->flush();
-                    if (_state[id].websocket) {
-                        INFO("MODE_WEBSOCKET");
-                        acceptWebsocket(id);
-                        _state[id].mode = MODE_WEBSOCKET;
-                    } else
-                    if (_state[id].length) {
-                        INFO("MODE_BODY");
-                        _state[id].mode = MODE_BODY;
-                    } else {
-                        INFO("MODE_ENTER");
-                        _state[id].mode = MODE_ENTER;
-                    }
-                }
-                _state[id].enter = c;
-                _state[id].buf->flush();
-                break;
-            }
-
-            parseHeader(id);
-            _state[id].enter = 0;
-            break;
-        default:
-            _state[id].buf->queue(c);
-            _state[id].enter = 0;
-            break;
-        }
-        break;
-    case MODE_BODY:
-        _state[id].buf->queue(c);
-        if (_state[id].buf->available() >= _state[id].length) {
-            _state[id].mode = MODE_ENTER;
-        }
-        break;
-    case MODE_WEBSOCKET:
-    case MODE_WEBSOCKET_MASK:
-    case MODE_WEBSOCKET_BODY:
-        recvWS(id, c);
-        break;
-    }
-
-    if (_state[id].mode == MODE_ENTER) {
-        int i = getHandler(_state[id].uri);
-        printf("handler = %d, uri = %s\r\n", i, _state[id].uri);
-        if (i >= 0) { 
-            if (_handler[i].dir) {
-                // file
-                httpdFile(id, _handler[i].dir);
-            } else if (_handler[i].funcCgi) {
-                // cgi
-                _handler[i].funcCgi(id);
-                _state[id].keepalive = 0;
-            } else {
-                httpdError(id, 403);
-            }
-        } else {
-            httpdError(id, 404);
-        }
-
-        if (_state[id].keepalive) {
-            DBG("keepalive %d", _state[id].keepalive);
-            _state[id].keepalive--;
-        } else {
-            _state[id].client->close();
-        }
-        _state[id].mode = MODE_REQUEST;
-    } else
-    if (_state[id].mode == MODE_WEBSOCKET_ENTER) {
-        parseWebsocket(id);
-        _state[id].mode = MODE_WEBSOCKET;
-    }
-}
-
-int HTTPD::parseRequest (int id) {
-    int i, j, len;
-    char buf[HTTPD_CMD_SIZE];
-
-    for (len = 0; len < sizeof(buf); len++) {
-        if (_state[id].buf->dequeue(&buf[len]) == false) break;
-    }
-    buf[len] = 0;
-
-    if (strnicmp(buf, "GET ", 4) == 0) {
-        _state[id].req = REQ_HTTPGET;
-        j = 4;
-    } else
-    if (strnicmp(buf, "POST ", 5) == 0) {
-        _state[id].req = REQ_HTTPPOST;
-        j = 5;
-    } else {
-        return -1;
-    }
-
-    for (i = 0; i < len - j; i ++) {
-        _state[id].uri[i] = buf[i + j];
-        if (buf[i + j] == ' ' || i >= sizeof(buf) - 1) {
-            _state[id].uri[i] = 0;
-            INFO("URI %d '%s'", _state[id].req, _state[id].uri);
-            _state[id].mode = MODE_HEADER;
-            _state[id].buf->flush();
-            _state[id].length = 0;
-            _state[id].n = 0;
-            _state[id].websocket = 0;
-            _state[id].filename = NULL;
-            _state[id].querystring = NULL;
-            break;
-        }
-    }
-
-    i = getHandler(_state[id].uri);
-    if (i >= 0) { 
-        _state[id].filename = &_state[id].uri[strlen(_handler[i].uri)];
-        for (i = 0; i < strlen(_state[id].filename); i ++) {
-            if (_state[id].filename[i] == '?') {
-                _state[id].filename[i] = 0;
-                _state[id].querystring = _state[id].filename + i + 1;
-                break;
-            }
-        }
-        INFO("FILE '%s' QUERY '%s'", _state[id].filename, _state[id].querystring);
-    }
-    return 0;
-}
-
-#define HEADER_TABLE_NUM 5
-int HTTPD::parseHeader (int id) {
-    int i;
-    char buf[HTTPD_CMD_SIZE];
-    static const struct HEADER_TABLE {
-        const char header[24];
-        void (HTTPD::*func)(int id, const char*);
-    } header_table[HEADER_TABLE_NUM] = {
-      {"Content-Length:",         &HTTPD::reqContentLength},
-      {"Connection:",             &HTTPD::reqConnection},
-      {"Upgrade: websocket",      &HTTPD::reqUpgrade},
-      {"Sec-WebSocket-Version:",  &HTTPD::reqWebSocketVersion},
-      {"Sec-WebSocket-Key:",      &HTTPD::reqWebSocketKey},
-    };
-    for (i = 0; i < sizeof(buf); i++) {
-        if (_state[id].buf->dequeue(&buf[i]) == false) break;
-    }
-    buf[i] = 0;
-
-    for (i = 0; i < HEADER_TABLE_NUM; i ++) {
-        if (strnicmp(buf, header_table[i].header, strlen(header_table[i].header)) == 0) {
-            DBG("parse header %d '%s'\r\n", i, buf);
-            if (header_table[i].func != NULL) {
-                (this->*(header_table[i].func))(id, buf);
-            }
-            return 0;
-        }
-    }
-
-    return -1;
-}
-
-void HTTPD::reqContentLength (int id, const char *buf) {
-    _state[id].length = atoi(&buf[16]);
-}
-
-void HTTPD::reqConnection (int id, const char *buf) {
-    if (strnicmp(&buf[12], "Keep-Alive", 10) == 0 && _state[id].keepalive == 0) {
-        _state[id].keepalive = HTTPD_KEEPALIVE;
-    } else {
-        _state[id].keepalive = 0;
-    }
-}
-
-void HTTPD::reqUpgrade (int id, const char *buf) {
-    if (! _state[id].websocket) _state[id].websocket = 1;
-}
-
-void HTTPD::reqWebSocketVersion (int id, const char *buf) {
-    _state[id].websocket = atoi(&buf[23]);
-}
-
-void HTTPD::reqWebSocketKey (int id, const char *buf) {
-    if (_state[id].websocket_key == NULL) {
-        _state[id].websocket_key = (char*)malloc(30);
-    }
-    strncpy(_state[id].websocket_key, &buf[19], 30);
-}
--- a/HTTPD_util.cpp	Thu Jun 29 10:17:29 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,256 +0,0 @@
-/* Copyright (C) 2013 Hiroshi Suga, MIT License
- *
- * 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.
- */
-
-#include "HTTPD.h"
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define MIMETABLE_NUM 9
-static const struct {
-    char ext[5];
-    char type[24];
-} mimetable[MIMETABLE_NUM] = {
-    {"txt", "text/plain"},  // default
-    {"html", "text/html"},
-    {"htm", "text/html"},
-    {"css", "text/css"},
-    {"js",  "application/javascript"},
-    {"jpg", "image/jpeg"},
-    {"png", "image/png"},
-    {"gif", "image/gif"},
-    {"ico", "image/x-icon"},
-};
-
-char *HTTPD::getUri (int id) {
-    return _state[id].uri;
-}
-
-char *HTTPD::getFilename (int id) {
-    return _state[id].filename;
-}
-
-char *HTTPD::getQueryString (int id) {
-    return _state[id].querystring;
-}
-
-int HTTPD::receive (int id, char *buf, int len) {
-    int i;
-
-    for (i = 0; i < len; i ++) {
-        if (_state[id].buf->dequeue(&buf[i]) == false) break;
-    }
-    return i;
-}
-
-int HTTPD::send (int id, const char *body, int len, const char *header) {
-    char buf[HTTPD_CMD_SIZE];
-
-    strcpy(buf, "HTTP/1.1 200 OK\r\n");
-    _state[id].client->send(buf, strlen(buf));
-    strcpy(buf, "Server: GSwifi httpd\r\n");
-    _state[id].client->send(buf, strlen(buf));
-    if (_state[id].keepalive) {
-        strcpy(buf, "Connection: Keep-Alive\r\n");
-    } else {
-        strcpy(buf, "Connection: close\r\n");
-    }
-    _state[id].client->send(buf, strlen(buf));
-    if (header) {
-        _state[id].client->send((char*)header, strlen(header));
-    }
-    sprintf(buf, "Content-Length: %d\r\n\r\n", len);
-    _state[id].client->send(buf, strlen(buf));
-
-    return _state[id].client->send((char*)body, len);
-}
-
-int HTTPD::sendstr (int id, const char *buf) {
-    return _state[id].client->send((char*)buf, strlen(buf));
-}
-
-
-int HTTPD::hprintf(int id, const char* format, ...) {
-    //FIX ME: This could result in memory overruns if the buffer size is exceeded
-    static Mutex _mtx;
-    static char  _buf[1024];
-
-    std::va_list arg;
-    
-    _mtx.lock();
-    
-    va_start(arg, format);
-    vsprintf(_buf, format, arg);
-    va_end(arg);
-
-    int r = _state[id].client->send(_buf, strlen(_buf));
-
-    _mtx.unlock();
-    return r;
-}
-
-int HTTPD::getHandler (const char *uri) {
-    int i;
-
-    for (i = 0; i < _handler_count; i ++) {
-        if (strncmp(uri, _handler[i].uri, strlen(_handler[i].uri)) == NULL) {
-            // found
-            return i;
-        }
-    }
-    return -1;
-}
-
-int HTTPD::attach (const char *uri, const char *dir) {
-    if (_handler_count < HTTPD_MAX_HANDLES) {
-        _handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1);
-        strcpy(_handler[_handler_count].uri, uri);
-        _handler[_handler_count].dir = (char*)malloc(strlen(dir) + 1);
-        strcpy(_handler[_handler_count].dir, dir);
-        _handler[_handler_count].funcCgi = NULL;
-        _handler_count ++;
-        return 0;
-    } else {
-        return -1;
-    }
-}
-
-int HTTPD::attach (const char *uri, void (*funcCgi)(int)) {
-    if (_handler_count < HTTPD_MAX_HANDLES) {
-        _handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1);
-        strcpy(_handler[_handler_count].uri, uri);
-        _handler[_handler_count].dir = NULL;
-        _handler[_handler_count].funcCgi = funcCgi;
-        _handler_count ++;
-        return 0;
-    } else {
-        return -1;
-    }
-}
-
-
-char *HTTPD::mimetype (char *file) {
-    int i, j;
-
-    for (i = 0; i < MIMETABLE_NUM; i ++) {
-        j = strlen(mimetable[i].ext);
-        if (file[strlen(file) - j - 1] == '.' &&
-          strnicmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) {
-            return (char*)mimetable[i].type;
-        }
-    }
-    return (char*)mimetable[0].type;
-}
-
-int HTTPD::strnicmp (const char *p1, const char *p2, int n) {
-    int i, r = -1;
-    char c1, c2;
-    
-    for (i = 0; i < n; i ++) {
-        c1 = (p1[i] >= 'a' && p1[i] <= 'z') ? p1[i] - ('a' - 'A'): p1[i];
-        c2 = (p2[i] >= 'a' && p2[i] <= 'z') ? p2[i] - ('a' - 'A'): p2[i];
-        r = c1 - c2;
-        if (r) break;
-    }
-    return r;
-}
-
-
-/* base64encode code from 
- * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
- */
-int HTTPD::base64encode (const char *input, int length, char *output, int len) {
-    static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-    unsigned int c, c1, c2, c3;
- 
-    if (len < ((((length-1)/3)+1)<<2)) return -1;
-    for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
-        c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
-        c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
-        c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
- 
-        c = ((c1 & 0xFC) >> 2);
-        output[j+0] = base64[c];
-        c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
-        output[j+1] = base64[c];
-        c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
-        output[j+2] = (length>i+1)?base64[c]:'=';
-        c = (c3 & 0x3F);
-        output[j+3] = (length>i+2)?base64[c]:'=';
-    }
-    output[(((length-1)/3)+1)<<2] = '\0';
-    return 0;
-}
- 
- 
-/* urlencode code from 
- * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
- */
-int HTTPD::urlencode (const char *str, char *buf, int len) {
-//  char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
-    const char *pstr = str;
-    char *pbuf = buf;
- 
-    if (len < (strlen(str) * 3 + 1)) return -1;
-    while (*pstr) {
-        if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
-            *pbuf++ = *pstr;
-        else if (*pstr == ' ') 
-            *pbuf++ = '+';
-        else 
-            *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
-        pstr++;
-    }
-    *pbuf = '\0';
-    return 0;
-}
- 
-/* urldecode code from 
- * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
- */
-int HTTPD::urldecode (const char *str, char *buf, int len) {
-//  char *pstr = str, *buf = (char*)malloc(strlen(str) + 1), *pbuf = buf;
-    const char *pstr = str;
-    char *pbuf = buf;
- 
-    if (len < (strlen(str) / 3 - 1)) return -1;
-    while (*pstr) {
-        if (*pstr == '%') {
-            if (pstr[1] && pstr[2]) {
-                *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
-                pstr += 2;
-            }
-        } else if (*pstr == '+') { 
-            *pbuf++ = ' ';
-        } else {
-            *pbuf++ = *pstr;
-        }
-        pstr++;
-    }
-    *pbuf = '\0';
-    return 0;
-}
-
-int HTTPD::from_hex (int ch) {
-  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
-}
- 
-int HTTPD::to_hex (int code) {
-  static char hex[] = "0123456789abcdef";
-  return hex[code & 15];
-}
--- a/HTTPD_ws.cpp	Thu Jun 29 10:17:29 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/* Copyright (C) 2013 Hiroshi Suga, MIT License
- *
- * 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.
- */
-
-#include "HTTPD.h"
-#include "sha1.h"
-
-void HTTPD::recvWS (int id, char c) {
-
-    switch (_state[id].mode) {
-    case MODE_WEBSOCKET:
-        if (_state[id].n == 0) {
-            // flag
-            _state[id].websocket_opcode = c & 0x0f;
-            _state[id].websocket_flg = c << 8;
-            _state[id].n ++;
-        } else
-        if (_state[id].n == 1) {
-            // length 7bit
-            _state[id].websocket_flg |= c;
-            _state[id].length = c & 0x7f;
-            _state[id].n ++;
-            if (_state[id].length < 126) {
-                _state[id].n = 0;
-                if (_state[id].length) {
-                    if (_state[id].websocket_flg & 0x0080) {
-                        _state[id].mode = MODE_WEBSOCKET_MASK;
-                    } else {
-                        _state[id].mode = MODE_WEBSOCKET_BODY;
-                    }
-                } else {
-                    _state[id].mode = MODE_WEBSOCKET_ENTER;
-                }
-                DBG("ws length %d\r\n", _state[id].length);
-            }
-        } else {
-            // length 16bit,64bit
-            if (_state[id].n == 2) {
-                _state[id].length = c;
-                _state[id].n ++;
-            } else
-            if (_state[id].n < 9 && (_state[id].websocket_flg & 0x7f) == 127) {
-                // 64bit
-                _state[id].length = (_state[id].length << 8) | c;
-                _state[id].n ++;
-            } else {
-                // end
-                _state[id].length = (_state[id].length << 8) | c;
-                _state[id].n = 0;
-                if (_state[id].websocket_flg & 0x0080) {
-                    _state[id].mode = MODE_WEBSOCKET_MASK;
-                } else {
-                    _state[id].mode = MODE_WEBSOCKET_BODY;
-                }
-                DBG("ws length2 %d\r\n", _state[id].length);
-            }
-        }
-        break;
-    case MODE_WEBSOCKET_MASK:
-        // masking key
-        _state[id].websocket_mask[_state[id].n] = c;
-        _state[id].n ++;
-        if (_state[id].n >= 4) {
-            _state[id].n = 0;
-            _state[id].mode = MODE_WEBSOCKET_BODY;
-            DBG("ws mask\r\n");
-        }
-        break;
-    case MODE_WEBSOCKET_BODY:
-        // payload
-        if (_state[id].websocket_flg & 0x0080) {
-            // un-mask
-            _state[id].buf->queue(c ^ _state[id].websocket_mask[_state[id].n & 0x03]); 
-        } else {
-            _state[id].buf->queue(c); 
-        }
-        _state[id].n ++;
-        if (_state[id].n >= _state[id].length) {
-            _state[id].mode = MODE_WEBSOCKET_ENTER;
-        }
-        break;
-    }
-}
-
-int HTTPD::parseWebsocket (int id) {
-    int i;
-
-    DBG("ws opcode %d\r\n", _state[id].websocket_opcode);
-    switch (_state[id].websocket_opcode) {
-    case 0x00: // continuation
-        break;
-    case 0x01: // text
-    case 0x02: // binary
-        i = getHandler(_state[id].uri);
-        if (i >= 0) {
-            if (_handler[i].funcCgi) {
-                // cgi
-                _handler[i].funcCgi(id);
-            }
-        }
-        break;
-    case 0x08: // close
-        _state[id].client->close();
-        break;
-    case 0x09: // ping
-        {
-        char pong[_state[id].n + 2];
-        pong[0] = 0x8a;
-        pong[1] = 0x04;
-        for (i = 0; i < _state[id].length; i ++) {
-            if (_state[id].buf->dequeue(&pong[i + 2]) == false) break;
-        }
-        _state[id].client->send(pong, _state[id].length + 2);
-        }
-        break;
-    case 0x0a: // pong
-        break;
-    default:
-        break;
-    }
-    _state[id].n = 0;
-    _state[id].length = 0;
-    return 0;
-}
-
-int HTTPD::acceptWebsocket (int id) {
-    char buf[HTTPD_CMD_SIZE], buf2[HTTPD_CMD_SIZE];
-    
-    DBG("websocket accept: %d\r\n", id);
-
-    strcpy(buf, "HTTP/1.1 101 Switching Protocols\r\n");
-    _state[id].client->send(buf, strlen(buf));
-    strcpy(buf, "Upgrade: websocket\r\n");
-    _state[id].client->send(buf, strlen(buf));
-    strcpy(buf, "Connection: Upgrade\r\n");
-    _state[id].client->send(buf, strlen(buf));
-
-    strcpy(buf, "Sec-WebSocket-Accept: ");
-    _state[id].client->send(buf, strlen(buf));
-    strcpy(buf, _state[id].websocket_key);
-    strcat(buf, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
-    sha1(buf, strlen(buf), buf2);
-    base64encode(buf2, 20, buf, sizeof(buf));
-    _state[id].client->send(buf, strlen(buf));
-    strcpy(buf, "\r\n\r\n");
-    _state[id].client->send(buf, strlen(buf));
-    //_state[id].client->set_blocking(true, HTTPD_TIMEOUT * 100);
-    return 0;
-}
-
-int HTTPD::sendWebsocket (int id, const char *buf, int len, const char *mask) {
-    HTTPD *httpd = HTTPD::getInstance();
-    int i = 0, r;
-    char tmp[10];
-
-    tmp[i++] = 0x81; // single, text frame
-    if (len < 126) {
-        tmp[i++] = (mask == NULL ? 0 : 0x80) | len;
-    } else {
-        tmp[i++] = (mask == NULL ? 0 : 0x80) | 126;
-        tmp[i++] = (len >> 8) & 0xff;
-        tmp[i++] = len & 0xff;
-    }
-    if (mask) {
-        memcpy(&tmp[i], mask, 4);
-        i += 4;
-    }
-    r = httpd->_state[id].client->send(tmp, i);
-
-    if (r >= 0) {
-        if (mask) {
-            char tmp2[len];
-            for (i = 0; i < len; i ++) {
-                tmp2[i] = buf[i] ^ mask[i & 0x03];
-            }
-            r = httpd->_state[id].client->send(tmp2, len);
-        } else {
-            r = httpd->_state[id].client->send((char*)buf, len);
-        }
-    }
-    return r;
-}
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ModBus-Req.cpp	Fri Jun 30 08:17:01 2017 +0000
@@ -0,0 +1,96 @@
+
+
+#include "ModBus-TCP.h"
+
+void Modbus::recvData (int id, char buffer[], int size) {
+    
+    int bytes_rec;
+    int returnLength;
+    unsigned short transaction_number;
+    unsigned short protokoll;
+    unsigned short number_of_bytes;
+    char adress;
+    int port;
+    
+    transaction_number = buffer[0] + (buffer[1] << 8);
+    protokoll = buffer[2] + (buffer[3] << 8);
+    number_of_bytes = (buffer[4] << 8) + buffer[5] ;
+    adress = buffer[6];
+                  
+    if(protokoll != 0x0000) {
+         printf("No Modbus protkoll");    
+    }
+            
+    #ifdef DEBUG
+    //printf("tn: 0x%x, p: 0x%x, nb: %i, a: %i\r\n", transaction_number, protokoll, number_of_bytes, adress);
+    #endif
+    
+    for(int i=0; i<8; i++) {
+        _state[id].start_message[i] = buffer[i];
+    }
+    
+    //returnLength = mb_handle_data(buffer, number_of_bytes);
+    
+    char fc; 
+    fc = buffer[7];
+    
+    
+    unsigned short start_adress;
+    unsigned short number_of_registers;
+   
+    
+    switch(fc) {
+        case 0x04: //return mb_read_register(data_in, length); 
+            //Read Requet received
+            // Getting Start Address and Length
+            
+            //DBG("Read Request received\r\n");
+            
+             start_adress = (buffer[8] << 8) + buffer[9];
+             number_of_registers = (buffer[10] << 8) + buffer[11];
+        
+             
+             int i = getHandler(0);
+             //DBG("GetHandler %i",i);
+             
+             if(number_of_registers < 0x0001 || number_of_registers > 0x007d ) {
+                mb_exception_handler(id, buffer, number_of_registers, 0x03);
+            }
+    
+            if(start_adress >= MODBUS_MAX_REGISTER) {
+                mb_exception_handler(id, buffer, number_of_registers, 0x02);            
+            }
+    
+            if(number_of_registers < 0x0001 || number_of_registers + start_adress > MODBUS_MAX_REGISTER) {
+                mb_exception_handler(id, buffer, number_of_registers, 0x04); 
+            }
+            
+            
+             
+            _handler[i].funcCgiRead(id, start_adress, number_of_registers);
+            break;
+        case 0x10: //return mb_write_register(data_in, length);
+            break;
+                
+        default:  mb_exception_handler(id, buffer, size, 0x01);
+                
+    }
+}
+
+int Modbus::mb_exception_handler(int id, char data_in[], unsigned short length, char error) {
+    unsigned short number_of_bytes;
+    
+    data_in[7] += 0x80;
+    data_in[8] += error;
+    
+    number_of_bytes = 3;
+            
+    data_in[4] = (char)(number_of_bytes >> 8);
+    data_in[5] = (char)(number_of_bytes & 0x00ff);
+    
+    sendToClient(id, data_in, number_of_bytes + 7);
+    
+    return 0;
+}
+
+
--- a/ModBus-TCP.cpp	Thu Jun 29 10:17:29 2017 +0000
+++ b/ModBus-TCP.cpp	Fri Jun 30 08:17:01 2017 +0000
@@ -26,13 +26,13 @@
     _handler_count = 0;
 }
 
-int Modbus::start (NetworkStack *ns, int port) {
+int Modbus::start (EthernetInterface *ns, int port) {
     int i;
 
     m_ns = ns;
     
     for (i = 0; i < MODBUS_MAX_CLIENTS; i ++) {
-        _state[i].buf = new CircBuffer<char>(MODBUS_BUF_SIZE);
+       // _state[i].buf = new CircBuffer<char>(MODBUS_BUF_SIZE);
         _state[i].thread = new Thread(osPriorityNormal, MODBUS_STACK_SIZE);
         _state[i].client = new TCPSocket();
         _state[i].thread->start(callback(child, (void*)i));
@@ -46,7 +46,7 @@
     _server.open(m_ns);
     _server.bind(port);
     _server.set_blocking(true);
-    _server.listen();
+    _server.listen(MODBUS_MAX_CLIENTS);
     _daemon = new Thread(osPriorityNormal, MODBUS_STACK_SIZE);
     _daemon->start(Modbus::daemon);
     return 0;
@@ -56,25 +56,27 @@
     Modbus *modbus = Modbus::getInstance();
     int i, t = 0;
 
-    INFO("Wait for new connection...\r\n");
+    
     for (;;) {
+        //DBG("Wait for new connection... child %i",t);
         if (t >= 0) {
             if (modbus->_server.accept(modbus->_state[t].client) == 0) {
                 INFO("accept %d\r\n", t);
-                modbus->_state[t].thread->signal_set(1);
+                modbus->_state[t].thread->signal_set(0x1);
             }
         } else {
 #ifdef HTTPD_ENABLE_CLOSER
             if (modbus->_server.accept(modbus->_state[MODBUS_MAX_CLIENTS].client) == 0) {
                 INFO("accept x\r\n");
-                modbus->_state[MODBUS_MAX_CLIENTS].thread->signal_set(1);
+                modbus->_state[MODBUS_MAX_CLIENTS].thread->signal_set(0x1);
             }
 #endif
         }
 
         t = -1;
         for (i = 0; i < MODBUS_MAX_CLIENTS; i ++) {
-            if (modbus->_state[i].thread->get_state() == Thread::WaitingAnd) {
+            //DBG("Child %i in State : %u", i, modbus->_state[i].thread->get_state());
+            if ( modbus->_state[i].thread->get_state() == Thread::WaitingThreadFlag) {
                 if (t < 0) t = i; // next empty thread
             }
         }
@@ -82,42 +84,52 @@
 }
 
 void Modbus::child (void const *arg) {
-    Modbus *modbus = ModBus::getInstance();
+    Modbus *modbus = Modbus::getInstance();
     int id = (int)arg;
     int i, n;
-    char buf[ModBus_BUF_SIZE];
+    char buf[MODBUS_BUF_SIZE];
 
     for (;;) {
-        Thread::signal_wait(1);
-        modbus->_state[id].mode = MODE_REQUEST;
-        modbus->_state[id].buf->flush();
-        modbus->_state[id].keepalive = 0;
-        INFO("Connection from client\r\n");
+        //DBG("child %i waiting for connection",id);
+        Thread::signal_wait(0x1);
+        
+       
+
+        INFO("Connection from client on child %i", id);
 //      INFO("Connection from %s\r\n", httpd->_state[id].client->get_ip_address());
 
-        modbus->_state[id].client->set_blocking(false);
-        modbus->_state[id].client->set_timeout(HTTPD_TIMEOUT);
-        
+        modbus->_state[id].client->set_blocking(true);
+        modbus->_state[id].client->set_timeout(15000);
+        time_t t1 = time(NULL);
         for (;;) {
             //if (! httpd->_state[id].client->is_connected()) break;
-
+            modbus->_state[id].client->set_blocking(true);
+            modbus->_state[id].client->set_timeout(15000);
             n = modbus->_state[id].client->recv(buf, sizeof(buf));
             
             if (n < 0 ) {
-                printf("HTTPD::child breaking n = %d\r\n", n);
+                printf("Modbus::child breaking n = %d\r\n", n);
                 break;
             }
-            buf[n] = 0;
-            //DBG("Recv %d ", n);
-            DBG("Recv %d '%s'", n, buf);
-
-            for (i = 0; i < n; i ++) {
-                modbus->recvData(id, buf[i]);
+            
+            if( n > 0 ) { // We received something
+                
+                t1 = time(NULL);
+            
+                //DBG("Recv %d bytes Content: %x", n, buf)
+            
+                modbus->recvData(id, buf, n);
             }
+            
+            if(abs((int)(time(NULL) - t1))> 15) {
+                DBG("Timeout in child %i",id);
+                break;    
+            }
+            
         }
 
         modbus->_state[id].client->close(); // Needs to bere moved 
-        INFO("Closed client connection\r\n");
+        INFO("Closed client connection");
         //INFO("Close %s\r\n", httpd->_state[id].client->get_ip_address());
     }
 }
--- a/ModBus-TCP.h	Thu Jun 29 10:17:29 2017 +0000
+++ b/ModBus-TCP.h	Fri Jun 30 08:17:01 2017 +0000
@@ -22,21 +22,24 @@
 #include "mbed.h"
 #include "rtos.h"
 #include "NetworkStack.h"
-#include "EthInterface.h"
-#include "CBuffer.h"
+#include "EthernetInterface.h"
+//#include "CBuffer.h"
 
-#define DEBUG
+//#define DEBUG
 
 #define MODBUS_TCP_PORT 502
-#define MODBUS_MAX_CLIENTS 5
+#define MODBUS_MAX_CLIENTS 3
 #define MODBUS_KEEPALIVE 10
-#define MODBUS_TIMEOUT 15000
-#define MODBUS_MAX_HANDLES 10
+#define MODBUS_TIMEOUT 50000
+#define MODBUS_MAX_HANDLES 2
+ 
+#define MODBUS_MAX_REGISTER 256
+ 
  
 #define MODBUS_CMD_SIZE 100
-#define MODBUS_BUF_SIZE 256
+#define MODBUS_BUF_SIZE 128
 #define MODBUS_STACK_SIZE (1024 * 6)
-//#define HTTPD_ENABLE_CLOSER
+//efine HTTPD_ENABLE_CLOSER
 
 //Debug is disabled by default
 #if defined(DEBUG) and (!defined(TARGET_LPC11U24))
@@ -55,58 +58,32 @@
 class Modbus {
 public:
 
-  enum Mode {
-        MODE_REQUEST,
-        MODE_REQSTR,
-        MODE_HEADER,
-        MODE_BODY,
-        MODE_ENTER,
-        MODE_ERROR,
-        MODE_WEBSOCKET,
-        MODE_WEBSOCKET_MASK,
-        MODE_WEBSOCKET_BODY,
-        MODE_WEBSOCKET_ENTER,
-    };
-
     struct STATE {
         Thread *thread;
         TCPSocket *client;
-        volatile Request req;
-        volatile Mode mode;
-        CircBuffer <char>*buf;
+        //volatile Request req;
+        //CircBuffer <char>*buf;
         
-  
-        char *querystring;
-        int enter;
-        int length;
-        int n;
-        int keepalive;
+        char start_message[8];
 
     };
 
     Modbus ();
     
-    int start (NetworkStack *ns, int port = MODBUS_TCP_PORT);
+    int start (EthernetInterface *ns, int port = MODBUS_TCP_PORT);
 
     // --- HTTPD_req.cpp ---
     void httpdError (int id, int err);
 
    
     // --- HTTPD_util.cpp ---
-        
-        
-        
     TCPSocket *getClientSocket(int id) {
-        if (id >= HTTPD_MAX_CLIENTS) return NULL;
+        if (id >= MODBUS_MAX_CLIENTS) return NULL;
         return _state[id].client;
     }
-    int send (int id, const char *body, int len, const char *header = NULL);
-    int sendstr (int id, const char *buf);
-    int hprintf(int id, const char* format, ...);
-    int receive (int id, char *buf, int len);
-    int attach (const char *uri, const char *dir);
-    int attach (const char *uri, void (*funcCgi)(int id));
-    
+    int send (int id, unsigned short buffer[], int len);
+
+    int attachRead (void (*funcCgi)(int id, unsigned short start_address, unsigned short length), int startRegister = 0);
 
     static Modbus * getInstance() {
         return _inst;
@@ -117,7 +94,7 @@
     Thread *_daemon;
     TCPServer _server;
     
-    NetworkStack *m_ns;
+    EthernetInterface *m_ns;
 
 #ifdef MODBUS_ENABLE_CLOSER
     struct STATE _state[MODBUS_MAX_CLIENTS + 1];
@@ -126,9 +103,9 @@
 #endif
 
     struct HANDLER {
-        char *uri;
-        char *dir;
-        void (*funcCgi)(int id);
+        int startRegister;
+        void (*funcCgiRead)(int id, unsigned short start_address, unsigned short length);
+        void (*funcCgiWrite)(int id);
     } _handler[MODBUS_MAX_HANDLES];
 
     int _handler_count;
@@ -138,22 +115,15 @@
     static void closer (void const *arg);
 
     // --- HTTPD_req.cpp ---
-    int httpdFile (int id, char *dir);
-    void recvData (int id, char c);
-    int parseRequest (int id);
-    int parseHeader (int id);
-    void reqContentLength (int id, const char *buf);
-    void reqConnection (int id, const char *buf);
-    void reqUpgrade (int id, const char *buf);
-    void reqWebSocketVersion (int id, const char *buf);
-    void reqWebSocketKey (int id, const char *buf);
+    
+    void recvData (int id, char buf[], int size);
+    int mb_exception_handler(int id, char data_in[], unsigned short length, char error);
 
 
 
     // --- HTTPD_util.cpp ---
-    int getHandler (const char *uri);
-    char *mimetype (char *file);
-    int strnicmp (const char *p1, const char *p2, int n);
+    int getHandler (int startRegister);
+    int sendToClient(int id, char buffer[], unsigned short len);
     int from_hex (int ch);
     int to_hex (int code);
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ModBus_util.cpp	Fri Jun 30 08:17:01 2017 +0000
@@ -0,0 +1,104 @@
+/* Copyright (C) 2013 Hiroshi Suga, MIT License
+ *
+ * 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.
+ */
+
+#include "ModBus-TCP.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+int Modbus::getHandler (int startRegister) {
+    int i;
+
+    for (i = 0; i < _handler_count; i ++) {
+        if (_handler[i].startRegister == startRegister) {
+            // found
+            return i;
+        }
+    }
+    return -1;
+}
+
+
+int Modbus::attachRead (void (*funcCgi)(int, unsigned short, unsigned short), int startRegister) {
+    if (_handler_count < MODBUS_MAX_HANDLES) {
+        _handler[_handler_count].startRegister = startRegister;
+        _handler[_handler_count].funcCgiRead = funcCgi;
+        _handler_count ++;
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+
+int Modbus::send (int id, unsigned short buffer[], int len) {
+    
+    char out[MODBUS_BUF_SIZE];
+     
+    
+    // Build MBAP Header
+    //Transaction Number :: Copy from Org message
+    out[0] = _state[id].start_message[0];
+    out[1] = _state[id].start_message[1];
+    
+    //Protcoll Identifier :: Always 0x0000
+    out[2] = 0x00;
+    out[3] = 0x00;
+    
+    // Length (bytes to follow after length bytes) of TCP Frame
+    out[4] = (char)(((len*2)+3)>> 8);
+    out[5] = (char)(((len*2)+3) & 0x00ff);
+    
+    //unit identifier (normally 0xff, but 0x00 is allowed
+    out[6] = 0xff;
+    
+    //MBAP Header build finished
+    
+    // Now the ModBus response
+    //Function code :: Copy from org message
+    out[7] = _state[id].start_message[7];
+    
+    //Byte count of Modbus response
+    out[8] = len*2;
+    
+    for(int i=0; i<len; i++) {
+        out[(i*2)+9] = (char)(buffer[i] >> 8);  
+        out[(i*2)+10] = (char)(buffer[i] & 0x00ff);  
+    }
+    
+   
+    
+    DBG("sending anser on child %i", id);
+    return _state[id].client->send(out, (len*2)+9);
+}
+
+int Modbus::sendToClient(int id, char buffer[], unsigned short len) {
+        return _state[id].client->send(buffer, len);
+ }
+ 
+
+int Modbus::from_hex (int ch) {
+  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+ 
+int Modbus::to_hex (int code) {
+  static char hex[] = "0123456789abcdef";
+  return hex[code & 15];
+}