Initial migration to platformIO
This commit is contained in:
		
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
.pio
 | 
			
		||||
.vscode/.browse.c_cpp.db*
 | 
			
		||||
.vscode/c_cpp_properties.json
 | 
			
		||||
.vscode/launch.json
 | 
			
		||||
.vscode/ipch
 | 
			
		||||
							
								
								
									
										39
									
								
								include/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								include/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
 | 
			
		||||
This directory is intended for project header files.
 | 
			
		||||
 | 
			
		||||
A header file is a file containing C declarations and macro definitions
 | 
			
		||||
to be shared between several project source files. You request the use of a
 | 
			
		||||
header file in your project source file (C, C++, etc) located in `src` folder
 | 
			
		||||
by including it, with the C preprocessing directive `#include'.
 | 
			
		||||
 | 
			
		||||
```src/main.c
 | 
			
		||||
 | 
			
		||||
#include "header.h"
 | 
			
		||||
 | 
			
		||||
int main (void)
 | 
			
		||||
{
 | 
			
		||||
 ...
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Including a header file produces the same results as copying the header file
 | 
			
		||||
into each source file that needs it. Such copying would be time-consuming
 | 
			
		||||
and error-prone. With a header file, the related declarations appear
 | 
			
		||||
in only one place. If they need to be changed, they can be changed in one
 | 
			
		||||
place, and programs that include the header file will automatically use the
 | 
			
		||||
new version when next recompiled. The header file eliminates the labor of
 | 
			
		||||
finding and changing all the copies as well as the risk that a failure to
 | 
			
		||||
find one copy will result in inconsistencies within a program.
 | 
			
		||||
 | 
			
		||||
In C, the usual convention is to give header files names that end with `.h'.
 | 
			
		||||
It is most portable to use only letters, digits, dashes, and underscores in
 | 
			
		||||
header file names, and at most one dot.
 | 
			
		||||
 | 
			
		||||
Read more about using header files in official GCC documentation:
 | 
			
		||||
 | 
			
		||||
* Include Syntax
 | 
			
		||||
* Include Operation
 | 
			
		||||
* Once-Only Headers
 | 
			
		||||
* Computed Includes
 | 
			
		||||
 | 
			
		||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
 | 
			
		||||
							
								
								
									
										46
									
								
								lib/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								lib/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
 | 
			
		||||
This directory is intended for project specific (private) libraries.
 | 
			
		||||
PlatformIO will compile them to static libraries and link into executable file.
 | 
			
		||||
 | 
			
		||||
The source code of each library should be placed in a an own separate directory
 | 
			
		||||
("lib/your_library_name/[here are source files]").
 | 
			
		||||
 | 
			
		||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
 | 
			
		||||
 | 
			
		||||
|--lib
 | 
			
		||||
|  |
 | 
			
		||||
|  |--Bar
 | 
			
		||||
|  |  |--docs
 | 
			
		||||
|  |  |--examples
 | 
			
		||||
|  |  |--src
 | 
			
		||||
|  |     |- Bar.c
 | 
			
		||||
|  |     |- Bar.h
 | 
			
		||||
|  |  |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
 | 
			
		||||
|  |
 | 
			
		||||
|  |--Foo
 | 
			
		||||
|  |  |- Foo.c
 | 
			
		||||
|  |  |- Foo.h
 | 
			
		||||
|  |
 | 
			
		||||
|  |- README --> THIS FILE
 | 
			
		||||
|
 | 
			
		||||
|- platformio.ini
 | 
			
		||||
|--src
 | 
			
		||||
   |- main.c
 | 
			
		||||
 | 
			
		||||
and a contents of `src/main.c`:
 | 
			
		||||
```
 | 
			
		||||
#include <Foo.h>
 | 
			
		||||
#include <Bar.h>
 | 
			
		||||
 | 
			
		||||
int main (void)
 | 
			
		||||
{
 | 
			
		||||
  ...
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
PlatformIO Library Dependency Finder will find automatically dependent
 | 
			
		||||
libraries scanning project source files.
 | 
			
		||||
 | 
			
		||||
More information about PlatformIO Library Dependency Finder
 | 
			
		||||
- https://docs.platformio.org/page/librarymanager/ldf.html
 | 
			
		||||
							
								
								
									
										16
									
								
								platformio.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								platformio.ini
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
; PlatformIO Project Configuration File
 | 
			
		||||
;
 | 
			
		||||
;   Build options: build flags, source filter
 | 
			
		||||
;   Upload options: custom upload port, speed and extra flags
 | 
			
		||||
;   Library options: dependencies, extra library storages
 | 
			
		||||
;   Advanced options: extra scripting
 | 
			
		||||
;
 | 
			
		||||
; Please visit documentation for the other options and examples
 | 
			
		||||
; https://docs.platformio.org/page/projectconf.html
 | 
			
		||||
 | 
			
		||||
[env:megaatmega2560]
 | 
			
		||||
platform = atmelavr
 | 
			
		||||
board = megaatmega2560
 | 
			
		||||
framework = arduino
 | 
			
		||||
lib_deps = arduino-libraries/Ethernet@^2.0.2
 | 
			
		||||
build_flags -DHOST_NAME=DepartureSign
 | 
			
		||||
@@ -1,80 +0,0 @@
 | 
			
		||||
#include "ProtocolDL.hpp"
 | 
			
		||||
 | 
			
		||||
ProtocolDL::ProtocolDL(Image& img):
 | 
			
		||||
    image(&img)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ProtocolDL::newByte(uint8_t data)
 | 
			
		||||
{
 | 
			
		||||
    switch(cnt)
 | 
			
		||||
    {
 | 
			
		||||
        case 0:
 | 
			
		||||
            complete = false;
 | 
			
		||||
            source.width = (data << 8);
 | 
			
		||||
            cnt = 1;
 | 
			
		||||
            break;
 | 
			
		||||
        
 | 
			
		||||
        case 1:
 | 
			
		||||
            source.width |= data;
 | 
			
		||||
            cnt = 2;
 | 
			
		||||
            break;
 | 
			
		||||
        
 | 
			
		||||
        case 2:
 | 
			
		||||
            source.height = (data << 8);
 | 
			
		||||
            cnt = 3;
 | 
			
		||||
            break;
 | 
			
		||||
        
 | 
			
		||||
        case 3:
 | 
			
		||||
            source.height |= data;
 | 
			
		||||
            cnt = 4;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case 4:
 | 
			
		||||
            source.delay = (data << 8);
 | 
			
		||||
            cnt = 5;
 | 
			
		||||
            break;
 | 
			
		||||
        
 | 
			
		||||
        case 5:
 | 
			
		||||
            source.delay |= data;
 | 
			
		||||
            image->set_size(source.width, source.height);
 | 
			
		||||
            source.x = 0;
 | 
			
		||||
            source.y = 0;
 | 
			
		||||
            cnt = 6;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
            for (int shift = 7; shift >= 0; shift--) {
 | 
			
		||||
                byte pixel = (data >> shift) & 1;
 | 
			
		||||
                image->set_pixel(source.x, source.y, pixel);
 | 
			
		||||
 | 
			
		||||
                if(source.x == (source.width - 1) && source.y == (source.height - 1))
 | 
			
		||||
                {
 | 
			
		||||
                    //this was the last pixel
 | 
			
		||||
                    complete = true;
 | 
			
		||||
                    cnt = 0;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    source.x++;
 | 
			
		||||
                    if (source.x >= source.width) {
 | 
			
		||||
                        source.x = 0;
 | 
			
		||||
                        source.y++;
 | 
			
		||||
                        if (source.y >= source.height) {
 | 
			
		||||
                            source.y = 0;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ProtocolDL::isComplete()
 | 
			
		||||
{
 | 
			
		||||
    return complete;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
#ifndef PROTOCOL_DL_HPP
 | 
			
		||||
#define PROTOCOL_DL_HPP
 | 
			
		||||
 | 
			
		||||
#include "image.hpp"
 | 
			
		||||
 | 
			
		||||
class ProtocolDL
 | 
			
		||||
{
 | 
			
		||||
    public:
 | 
			
		||||
    ProtocolDL(Image& img);
 | 
			
		||||
    void newByte(uint8_t data);
 | 
			
		||||
    bool isComplete();
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    struct source_t {
 | 
			
		||||
        // width and height of current frame
 | 
			
		||||
        unsigned int width;
 | 
			
		||||
        unsigned int height;
 | 
			
		||||
 | 
			
		||||
        // delay until next frame is shown
 | 
			
		||||
        unsigned int delay;
 | 
			
		||||
 | 
			
		||||
        // position of current pixel
 | 
			
		||||
        int x;
 | 
			
		||||
        int y;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    source_t source;
 | 
			
		||||
    uint16_t cnt = 0;
 | 
			
		||||
    bool complete = true;
 | 
			
		||||
    Image* image;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,592 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file WebSockets.cpp
 | 
			
		||||
 * @date 20.05.2015
 | 
			
		||||
 * @author Markus Sattler
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2015 Markus Sattler. All rights reserved.
 | 
			
		||||
 * This file is part of the WebSockets for Arduino.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2.1 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "WebSockets.h"
 | 
			
		||||
 | 
			
		||||
#define LEGACY_SHA1
 | 
			
		||||
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
#include <core_esp8266_features.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
#ifdef CORE_HAS_LIBB64
 | 
			
		||||
    #include <libb64/cencode.h>
 | 
			
		||||
#else
 | 
			
		||||
    #include "libb64/cencode_inc.h"
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
#include <Hash.h>
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef LEGACY_SHA1
 | 
			
		||||
    #include "sha1/sha1.h"
 | 
			
		||||
#else
 | 
			
		||||
    extern "C" {
 | 
			
		||||
        #include "libsha1/libsha1.h"
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define WEBSOCKETS_MAX_HEADER_SIZE  (14)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 * @param code uint16_t see RFC
 | 
			
		||||
 * @param reason
 | 
			
		||||
 * @param reasonLen
 | 
			
		||||
 */
 | 
			
		||||
void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * reason, size_t reasonLen) {
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
	DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
    DEBUG_WEBSOCKETS("][handleWebsocket] clientDisconnect code: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(code);
 | 
			
		||||
    DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
    if(client->status == WSC_CONNECTED && code) {
 | 
			
		||||
        if(reason) {
 | 
			
		||||
            sendFrame(client, WSop_close, (uint8_t *) reason, reasonLen);
 | 
			
		||||
        } else {
 | 
			
		||||
            uint8_t buffer[2];
 | 
			
		||||
            buffer[0] = ((code >> 8) & 0xFF);
 | 
			
		||||
            buffer[1] = (code & 0xFF);
 | 
			
		||||
            sendFrame(client, WSop_close, &buffer[0], 2);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    clientDisconnect(client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @param client WSclient_t *   ptr to the client struct
 | 
			
		||||
 * @param opcode WSopcode_t
 | 
			
		||||
 * @param payload uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @param mask bool             add dummy mask to the frame (needed for web browser)
 | 
			
		||||
 * @param fin bool              can be used to send data in more then one frame (set fin on the last frame)
 | 
			
		||||
 * @param headerToPayload bool  set true if the payload has reserved 14 Byte at the beginning to dynamically add the Header (payload neet to be in RAM!)
 | 
			
		||||
 */
 | 
			
		||||
bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool mask, bool fin, bool headerToPayload) {
 | 
			
		||||
 | 
			
		||||
    if(client->tcp && !client->tcp->connected()) {
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
	    DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
        DEBUG_WEBSOCKETS("][sendFrame] not Connected!?\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(client->status != WSC_CONNECTED) {
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS][");        
 | 
			
		||||
	    DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
        DEBUG_WEBSOCKETS("][sendFrame] not in WSC_CONNECTED state!?\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS][");    
 | 
			
		||||
	DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
    DEBUG_WEBSOCKETS("][sendFrame] ------- send massage frame -------\n");
 | 
			
		||||
    
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
	DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
    DEBUG_WEBSOCKETS("][sendFrame] fin: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(fin);
 | 
			
		||||
    DEBUG_WEBSOCKETS(" opCode: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(opcode);
 | 
			
		||||
    DEBUG_WEBSOCKETS(" mask: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(mask);
 | 
			
		||||
    DEBUG_WEBSOCKETS(" length: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(length);
 | 
			
		||||
    DEBUG_WEBSOCKETS(" headerToPayload: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(headerToPayload);
 | 
			
		||||
    DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
    if(opcode == WSop_text) {
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
        DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
        DEBUG_WEBSOCKETS("][sendFrame] text: ");
 | 
			
		||||
        DEBUG_WEBSOCKETS((char*) (payload + (headerToPayload ? 14 : 0)));
 | 
			
		||||
        DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 };
 | 
			
		||||
    uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 };
 | 
			
		||||
 | 
			
		||||
    uint8_t headerSize;
 | 
			
		||||
    uint8_t * headerPtr;
 | 
			
		||||
    uint8_t * payloadPtr = payload;
 | 
			
		||||
    bool useInternBuffer = false;
 | 
			
		||||
    bool ret = true;
 | 
			
		||||
 | 
			
		||||
    // calculate header Size
 | 
			
		||||
    if(length < 126) {
 | 
			
		||||
        headerSize = 2;
 | 
			
		||||
    } else if(length < 0xFFFF) {
 | 
			
		||||
        headerSize = 4;
 | 
			
		||||
    } else {
 | 
			
		||||
        headerSize = 10;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(mask) {
 | 
			
		||||
        headerSize += 4;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef WEBSOCKETS_USE_BIG_MEM
 | 
			
		||||
    // only for ESP since AVR has less HEAP
 | 
			
		||||
    // try to send data in one TCP package (only if some free Heap is there)
 | 
			
		||||
    if(!headerToPayload && ((length > 0) && (length < 1400)) && (ESP.getFreeHeap() > 6000)) {
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
        DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
        DEBUG_WEBSOCKETS("][sendFrame] pack to one TCP package...\n");
 | 
			
		||||
        
 | 
			
		||||
        uint8_t * dataPtr = (uint8_t *) malloc(length + WEBSOCKETS_MAX_HEADER_SIZE);
 | 
			
		||||
        if(dataPtr) {
 | 
			
		||||
            memcpy((dataPtr + WEBSOCKETS_MAX_HEADER_SIZE), payload, length);
 | 
			
		||||
            headerToPayload = true;
 | 
			
		||||
            useInternBuffer = true;
 | 
			
		||||
            payloadPtr = dataPtr;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // set Header Pointer
 | 
			
		||||
    if(headerToPayload) {
 | 
			
		||||
        // calculate offset in payload
 | 
			
		||||
        headerPtr = (payloadPtr + (WEBSOCKETS_MAX_HEADER_SIZE - headerSize));
 | 
			
		||||
    } else {
 | 
			
		||||
        headerPtr = &buffer[0];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // create header
 | 
			
		||||
 | 
			
		||||
    // byte 0
 | 
			
		||||
    *headerPtr = 0x00;
 | 
			
		||||
    if(fin) {
 | 
			
		||||
        *headerPtr |= bit(7);    ///< set Fin
 | 
			
		||||
    }
 | 
			
		||||
    *headerPtr |= opcode;        ///< set opcode
 | 
			
		||||
    headerPtr++;
 | 
			
		||||
 | 
			
		||||
    // byte 1
 | 
			
		||||
    *headerPtr = 0x00;
 | 
			
		||||
    if(mask) {
 | 
			
		||||
        *headerPtr |= bit(7);    ///< set mask
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(length < 126) {
 | 
			
		||||
        *headerPtr |= length;                   headerPtr++;
 | 
			
		||||
    } else if(length < 0xFFFF) {
 | 
			
		||||
        *headerPtr |= 126;                      headerPtr++;
 | 
			
		||||
        *headerPtr = ((length >> 8) & 0xFF);    headerPtr++;
 | 
			
		||||
        *headerPtr = (length & 0xFF);           headerPtr++;
 | 
			
		||||
    } else {
 | 
			
		||||
        // Normally we never get here (to less memory)
 | 
			
		||||
        *headerPtr |= 127;                      headerPtr++;
 | 
			
		||||
        *headerPtr = 0x00;                      headerPtr++;
 | 
			
		||||
        *headerPtr = 0x00;                      headerPtr++;
 | 
			
		||||
        *headerPtr = 0x00;                      headerPtr++;
 | 
			
		||||
        *headerPtr = 0x00;                      headerPtr++;
 | 
			
		||||
        *headerPtr = ((length >> 24) & 0xFF);   headerPtr++;
 | 
			
		||||
        *headerPtr = ((length >> 16) & 0xFF);   headerPtr++;
 | 
			
		||||
        *headerPtr = ((length >> 8) & 0xFF);    headerPtr++;
 | 
			
		||||
        *headerPtr = (length & 0xFF);           headerPtr++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(mask) {
 | 
			
		||||
        if(useInternBuffer) {
 | 
			
		||||
            // if we use a Intern Buffer we can modify the data
 | 
			
		||||
            // by this fact its possible the do the masking
 | 
			
		||||
            for(uint8_t x = 0; x < sizeof(maskKey); x++) {
 | 
			
		||||
                maskKey[x] = random(0xFF);
 | 
			
		||||
                *headerPtr = maskKey[x];       headerPtr++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            uint8_t * dataMaskPtr;
 | 
			
		||||
 | 
			
		||||
            if(headerToPayload) {
 | 
			
		||||
                dataMaskPtr = (payloadPtr + WEBSOCKETS_MAX_HEADER_SIZE);
 | 
			
		||||
            } else {
 | 
			
		||||
                dataMaskPtr = payloadPtr;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for(size_t x = 0; x < length; x++) {
 | 
			
		||||
                dataMaskPtr[x] = (dataMaskPtr[x] ^ maskKey[x % 4]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            *headerPtr = maskKey[0];          headerPtr++;
 | 
			
		||||
            *headerPtr = maskKey[1];          headerPtr++;
 | 
			
		||||
            *headerPtr = maskKey[2];          headerPtr++;
 | 
			
		||||
            *headerPtr = maskKey[3];          headerPtr++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef NODEBUG_WEBSOCKETS
 | 
			
		||||
    unsigned long start = micros();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if(headerToPayload) {
 | 
			
		||||
        // header has be added to payload
 | 
			
		||||
        // payload is forced to reserved 14 Byte but we may not need all based on the length and mask settings
 | 
			
		||||
        // offset in payload is calculatetd 14 - headerSize
 | 
			
		||||
        if (client->tcp->write(&payloadPtr[(WEBSOCKETS_MAX_HEADER_SIZE - headerSize)], (length + headerSize)) != (length + headerSize)) {
 | 
			
		||||
            ret = false;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        // send header
 | 
			
		||||
        if (client->tcp->write(&buffer[0], headerSize) != headerSize) {
 | 
			
		||||
            ret = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(payloadPtr && length > 0) {
 | 
			
		||||
            // send payload
 | 
			
		||||
            if(client->tcp->write(&payloadPtr[0], length) != length) {
 | 
			
		||||
                ret = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
	DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
    DEBUG_WEBSOCKETS("][sendFrame] sending Frame Done (");
 | 
			
		||||
	DEBUG_WEBSOCKETS((micros() - start));
 | 
			
		||||
    DEBUG_WEBSOCKETS("us).\n");
 | 
			
		||||
 | 
			
		||||
#ifdef WEBSOCKETS_USE_BIG_MEM
 | 
			
		||||
    if(useInternBuffer && payloadPtr) {
 | 
			
		||||
        free(payloadPtr);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * handle the WebSocket stream
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 */
 | 
			
		||||
void WebSockets::handleWebsocket(WSclient_t * client) {
 | 
			
		||||
 | 
			
		||||
    uint8_t buffer[8] = { 0 };
 | 
			
		||||
 | 
			
		||||
    bool fin;
 | 
			
		||||
    bool rsv1;
 | 
			
		||||
    bool rsv2;
 | 
			
		||||
    bool rsv3;
 | 
			
		||||
    WSopcode_t opCode;
 | 
			
		||||
    bool mask;
 | 
			
		||||
    size_t payloadLen;
 | 
			
		||||
 | 
			
		||||
    uint8_t maskKey[4];
 | 
			
		||||
 | 
			
		||||
    uint8_t * payload = NULL;
 | 
			
		||||
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
	DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
    DEBUG_WEBSOCKETS("][handleWebsocket] ------- read massage frame -------\n");
 | 
			
		||||
 | 
			
		||||
    if(!readWait(client, buffer, 2)) {
 | 
			
		||||
        //timeout
 | 
			
		||||
        clientDisconnect(client, 1002);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // split first 2 bytes in the data
 | 
			
		||||
    fin = ((buffer[0] >> 7) & 0x01);
 | 
			
		||||
    rsv1 = ((buffer[0] >> 6) & 0x01);
 | 
			
		||||
    rsv2 = ((buffer[0] >> 5) & 0x01);
 | 
			
		||||
    rsv3 = ((buffer[0] >> 4) & 0x01);
 | 
			
		||||
    opCode = (WSopcode_t) (buffer[0] & 0x0F);
 | 
			
		||||
 | 
			
		||||
    mask = ((buffer[1] >> 7) & 0x01);
 | 
			
		||||
    payloadLen = (WSopcode_t) (buffer[1] & 0x7F);
 | 
			
		||||
 | 
			
		||||
    if(payloadLen == 126) {
 | 
			
		||||
        if(!readWait(client, buffer, 2)) {
 | 
			
		||||
            //timeout
 | 
			
		||||
            clientDisconnect(client, 1002);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        payloadLen = buffer[0] << 8 | buffer[1];
 | 
			
		||||
    } else if(payloadLen == 127) {
 | 
			
		||||
        // read 64bit integer as length
 | 
			
		||||
        if(!readWait(client, buffer, 8)) {
 | 
			
		||||
            //timeout
 | 
			
		||||
            clientDisconnect(client, 1002);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(buffer[0] != 0 || buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0) {
 | 
			
		||||
            // really to big!
 | 
			
		||||
            payloadLen = 0xFFFFFFFF;
 | 
			
		||||
        } else {
 | 
			
		||||
            payloadLen = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
	DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
    DEBUG_WEBSOCKETS("][handleWebsocket] fin: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(fin);
 | 
			
		||||
    DEBUG_WEBSOCKETS(" rsv1: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(rsv1);
 | 
			
		||||
    DEBUG_WEBSOCKETS(" rsv2: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(rsv2);
 | 
			
		||||
    DEBUG_WEBSOCKETS(" rsv3: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(rsv3);
 | 
			
		||||
    DEBUG_WEBSOCKETS(" opCode: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(opCode);
 | 
			
		||||
    DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
    
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
	DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
    DEBUG_WEBSOCKETS("][handleWebsocket] mask: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(mask);
 | 
			
		||||
    DEBUG_WEBSOCKETS(" payloadLen: ");
 | 
			
		||||
	DEBUG_WEBSOCKETS(payloadLen);
 | 
			
		||||
    DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
    if(payloadLen > WEBSOCKETS_MAX_DATA_SIZE) {
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
	    DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
        DEBUG_WEBSOCKETS("][handleWebsocket] payload to big! (");
 | 
			
		||||
        DEBUG_WEBSOCKETS(payloadLen);
 | 
			
		||||
        DEBUG_WEBSOCKETS(")\n");
 | 
			
		||||
        clientDisconnect(client, 1009);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(mask) {
 | 
			
		||||
        if(!readWait(client, maskKey, 4)) {
 | 
			
		||||
            //timeout
 | 
			
		||||
            clientDisconnect(client, 1002);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(payloadLen > 0) {
 | 
			
		||||
        // if text data we need one more
 | 
			
		||||
        payload = (uint8_t *) malloc(payloadLen + 1);
 | 
			
		||||
 | 
			
		||||
        if(!payload) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
            DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
            DEBUG_WEBSOCKETS("][handleWebsocket] to less memory to handle payload ");
 | 
			
		||||
            DEBUG_WEBSOCKETS(payloadLen);
 | 
			
		||||
            DEBUG_WEBSOCKETS("!\n");
 | 
			
		||||
            clientDisconnect(client, 1011);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!readWait(client, payload, payloadLen)) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
            DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
            DEBUG_WEBSOCKETS("][handleWebsocket] missing data!\n");
 | 
			
		||||
            free(payload);
 | 
			
		||||
            clientDisconnect(client, 1002);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        payload[payloadLen] = 0x00;
 | 
			
		||||
 | 
			
		||||
        if(mask) {
 | 
			
		||||
            //decode XOR
 | 
			
		||||
            for(size_t i = 0; i < payloadLen; i++) {
 | 
			
		||||
                payload[i] = (payload[i] ^ maskKey[i % 4]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch(opCode) {
 | 
			
		||||
        case WSop_text:
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
            DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
            DEBUG_WEBSOCKETS("][handleWebsocket] text: ");
 | 
			
		||||
            DEBUG_WEBSOCKETS((char*) payload);
 | 
			
		||||
            DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
            // no break here!
 | 
			
		||||
        case WSop_binary:
 | 
			
		||||
            messageRecived(client, opCode, payload, payloadLen);
 | 
			
		||||
            break;
 | 
			
		||||
        case WSop_ping:
 | 
			
		||||
            // send pong back
 | 
			
		||||
            sendFrame(client, WSop_pong, payload, payloadLen);
 | 
			
		||||
            break;
 | 
			
		||||
        case WSop_pong:
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
            DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
            DEBUG_WEBSOCKETS("][handleWebsocket] get pong  (");
 | 
			
		||||
            DEBUG_WEBSOCKETS((char*) payload);
 | 
			
		||||
            DEBUG_WEBSOCKETS(")\n");
 | 
			
		||||
            break;
 | 
			
		||||
        case WSop_close:
 | 
			
		||||
            {
 | 
			
		||||
                uint16_t reasonCode = 1000;
 | 
			
		||||
                if(payloadLen >= 2) {
 | 
			
		||||
                    reasonCode = payload[0] << 8 | payload[1];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                DEBUG_WEBSOCKETS("[WS][");
 | 
			
		||||
                DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
                DEBUG_WEBSOCKETS("][handleWebsocket] get ask for close. Code: ");
 | 
			
		||||
                DEBUG_WEBSOCKETS(reasonCode);
 | 
			
		||||
                if(payloadLen > 2) {
 | 
			
		||||
                    DEBUG_WEBSOCKETS(" (");
 | 
			
		||||
                    DEBUG_WEBSOCKETS((char*) (payload+2));
 | 
			
		||||
                    DEBUG_WEBSOCKETS(")\n");
 | 
			
		||||
                } else {
 | 
			
		||||
                    DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
                }
 | 
			
		||||
                clientDisconnect(client, 1000);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case WSop_continuation:
 | 
			
		||||
            // continuation is not supported
 | 
			
		||||
            clientDisconnect(client, 1003);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            clientDisconnect(client, 1002);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(payload) {
 | 
			
		||||
        free(payload);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * generate the key for Sec-WebSocket-Accept
 | 
			
		||||
 * @param clientKey String
 | 
			
		||||
 * @return String Accept Key
 | 
			
		||||
 */
 | 
			
		||||
String WebSockets::acceptKey(String clientKey) {
 | 
			
		||||
    uint8_t sha1HashBin[20] = { 0 };
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
    sha1(clientKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", &sha1HashBin[0]);
 | 
			
		||||
#else
 | 
			
		||||
    clientKey += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
 | 
			
		||||
    #ifdef LEGACY_SHA1
 | 
			
		||||
      // Miha Nahtigal
 | 
			
		||||
      char cbuff[clientKey.length()+1];
 | 
			
		||||
      clientKey.toCharArray(cbuff, clientKey.length()+1);//Converts String into character array 
 | 
			
		||||
      Sha1.init();
 | 
			
		||||
      Sha1.print(cbuff);
 | 
			
		||||
      strcpy(sha1HashBin, Sha1.result());
 | 
			
		||||
      Serial.println(cbuff);
 | 
			
		||||
      //old:uint8_t *sha1HashBin = Sha1.result();     
 | 
			
		||||
    #else
 | 
			
		||||
      SHA1_CTX ctx;
 | 
			
		||||
      SHA1Init(&ctx);           
 | 
			
		||||
      SHA1Update(&ctx, (const unsigned char*)clientKey.c_str(), clientKey.length());
 | 
			
		||||
      SHA1Final(&sha1HashBin[0], &ctx); 
 | 
			
		||||
    #endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    String key = base64_encode(sha1HashBin, 20); 
 | 
			
		||||
    key.trim();
 | 
			
		||||
 | 
			
		||||
    return key;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * base64_encode
 | 
			
		||||
 * @param data uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @return base64 encoded String
 | 
			
		||||
 */
 | 
			
		||||
String WebSockets::base64_encode(uint8_t * data, size_t length) {
 | 
			
		||||
    size_t size = ((length*1.6f)+1);
 | 
			
		||||
    char * buffer = (char *) malloc(size);
 | 
			
		||||
    if(buffer) {
 | 
			
		||||
        base64_encodestate _state;
 | 
			
		||||
        base64_init_encodestate(&_state);
 | 
			
		||||
        int len = base64_encode_block((const char *) &data[0], length, &buffer[0], &_state);
 | 
			
		||||
        len = base64_encode_blockend((buffer + len), &_state);
 | 
			
		||||
 | 
			
		||||
        String base64 = String(buffer);
 | 
			
		||||
        free(buffer);
 | 
			
		||||
        return base64;
 | 
			
		||||
    }
 | 
			
		||||
    return String("-FAIL-");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * read x byte from tcp or get timeout
 | 
			
		||||
 * @param client WSclient_t *
 | 
			
		||||
 * @param out  uint8_t * data buffer
 | 
			
		||||
 * @param n size_t byte count
 | 
			
		||||
 * @return true if ok
 | 
			
		||||
 */
 | 
			
		||||
bool WebSockets::readWait(WSclient_t * client, uint8_t *out, size_t n) {
 | 
			
		||||
    unsigned long t = millis();
 | 
			
		||||
    size_t len;
 | 
			
		||||
 | 
			
		||||
    while(n > 0) {
 | 
			
		||||
        if(!client->tcp) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[readWait] tcp is null!\n");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!client->tcp->connected()) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[readWait] not connected!\n");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if((millis() - t) > WEBSOCKETS_TCP_TIMEOUT) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[readWait] receive TIMEOUT!\n");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!client->tcp->available()) {
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
            delay(0);
 | 
			
		||||
#endif
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        len = client->tcp->read((uint8_t*) out, n);
 | 
			
		||||
        if(len) {
 | 
			
		||||
            t = millis();
 | 
			
		||||
            out += len;
 | 
			
		||||
            n -= len;
 | 
			
		||||
            //DEBUG_WEBSOCKETS("Receive %d left %d!\n", len, n);
 | 
			
		||||
        } else {
 | 
			
		||||
            //DEBUG_WEBSOCKETS("Receive %d left %d!\n", len, n);
 | 
			
		||||
        }
 | 
			
		||||
        //DEBUG_WEBSOCKETS("Receive ");
 | 
			
		||||
        //DEBUG_WEBSOCKETS(len);
 | 
			
		||||
        //DEBUG_WEBSOCKETS("left ");
 | 
			
		||||
        //DEBUG_WEBSOCKETS(n);      
 | 
			
		||||
        //DEBUG_WEBSOCKETS("!\n");                  
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
        delay(0);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										159
									
								
								src/WebSockets.h
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								src/WebSockets.h
									
									
									
									
									
								
							@@ -1,159 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file WebSockets.h
 | 
			
		||||
 * @date 20.05.2015
 | 
			
		||||
 * @author Markus Sattler
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2015 Markus Sattler. All rights reserved.
 | 
			
		||||
 * This file is part of the WebSockets for Arduino.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2.1 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef WEBSOCKETS_H_
 | 
			
		||||
#define WEBSOCKETS_H_
 | 
			
		||||
 | 
			
		||||
#include <Arduino.h>
 | 
			
		||||
 | 
			
		||||
//#define DEBUG_WEBSOCKETS(...) Serial.print( __VA_ARGS__ )
 | 
			
		||||
 | 
			
		||||
#ifndef DEBUG_WEBSOCKETS
 | 
			
		||||
#define DEBUG_WEBSOCKETS(...)
 | 
			
		||||
#define NODEBUG_WEBSOCKETS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
#define WEBSOCKETS_MAX_DATA_SIZE  (15*1024)
 | 
			
		||||
#define WEBSOCKETS_USE_BIG_MEM
 | 
			
		||||
#else
 | 
			
		||||
//atmega328p has only 2KB ram!
 | 
			
		||||
#define WEBSOCKETS_MAX_DATA_SIZE  (2048)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define WEBSOCKETS_TCP_TIMEOUT    (1500)
 | 
			
		||||
 | 
			
		||||
#define NETWORK_ESP8266     (1)
 | 
			
		||||
#define NETWORK_W5100       (2)
 | 
			
		||||
#define NETWORK_ENC28J60    (3)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// select Network type based
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP8266
 | 
			
		||||
#else
 | 
			
		||||
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
 | 
			
		||||
#ifndef ESP8266
 | 
			
		||||
#error "network type ESP8266 only possible on the ESP mcu!"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <ESP8266WiFi.h>
 | 
			
		||||
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
 | 
			
		||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
 | 
			
		||||
 | 
			
		||||
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100)
 | 
			
		||||
 | 
			
		||||
#include <Ethernet.h>
 | 
			
		||||
#include <SPI.h>
 | 
			
		||||
#define WEBSOCKETS_NETWORK_CLASS EthernetClient
 | 
			
		||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer
 | 
			
		||||
 | 
			
		||||
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ENC28J60)
 | 
			
		||||
 | 
			
		||||
#include <UIPEthernet.h>
 | 
			
		||||
#define WEBSOCKETS_NETWORK_CLASS UIPClient
 | 
			
		||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS UIPServer
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#error "no network type selected!"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    WSC_NOT_CONNECTED,
 | 
			
		||||
    WSC_HEADER,
 | 
			
		||||
    WSC_CONNECTED
 | 
			
		||||
} WSclientsStatus_t;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    WStype_ERROR,
 | 
			
		||||
    WStype_DISCONNECTED,
 | 
			
		||||
    WStype_CONNECTED,
 | 
			
		||||
    WStype_TEXT,
 | 
			
		||||
    WStype_BIN
 | 
			
		||||
} WStype_t;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    WSop_continuation = 0x00, ///< %x0 denotes a continuation frame
 | 
			
		||||
    WSop_text = 0x01,         ///< %x1 denotes a text frame
 | 
			
		||||
    WSop_binary = 0x02,       ///< %x2 denotes a binary frame
 | 
			
		||||
                              ///< %x3-7 are reserved for further non-control frames
 | 
			
		||||
    WSop_close = 0x08,        ///< %x8 denotes a connection close
 | 
			
		||||
    WSop_ping = 0x09,         ///< %x9 denotes a ping
 | 
			
		||||
    WSop_pong = 0x0A          ///< %xA denotes a pong
 | 
			
		||||
                              ///< %xB-F are reserved for further control frames
 | 
			
		||||
} WSopcode_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
        uint8_t num; ///< connection number
 | 
			
		||||
 | 
			
		||||
        WSclientsStatus_t status;
 | 
			
		||||
 | 
			
		||||
        WEBSOCKETS_NETWORK_CLASS * tcp;
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
        bool isSSL;             ///< run in ssl mode
 | 
			
		||||
        WiFiClientSecure * ssl;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        String cUrl;        ///< http url
 | 
			
		||||
        uint16_t cCode;     ///< http code
 | 
			
		||||
 | 
			
		||||
        bool cIsUpgrade;    ///< Connection == Upgrade
 | 
			
		||||
        bool cIsWebsocket;  ///< Upgrade == websocket
 | 
			
		||||
 | 
			
		||||
        String cKey;        ///< client Sec-WebSocket-Key
 | 
			
		||||
        String cAccept;     ///< client Sec-WebSocket-Accept
 | 
			
		||||
        String cProtocol;   ///< client Sec-WebSocket-Protocol
 | 
			
		||||
        String cExtensions; ///< client Sec-WebSocket-Extensions
 | 
			
		||||
        uint16_t cVersion;  ///< client Sec-WebSocket-Version
 | 
			
		||||
 | 
			
		||||
} WSclient_t;
 | 
			
		||||
 | 
			
		||||
class WebSockets {
 | 
			
		||||
    protected:
 | 
			
		||||
        virtual void clientDisconnect(WSclient_t * client);
 | 
			
		||||
        virtual bool clientIsConnected(WSclient_t * client);
 | 
			
		||||
 | 
			
		||||
        virtual void messageRecived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
 | 
			
		||||
 | 
			
		||||
        void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
 | 
			
		||||
        bool sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool mask = false, bool fin = true, bool headerToPayload = false);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        void handleWebsocket(WSclient_t * client);
 | 
			
		||||
 | 
			
		||||
        bool readWait(WSclient_t * client, uint8_t *out, size_t n);
 | 
			
		||||
 | 
			
		||||
        String acceptKey(String clientKey);
 | 
			
		||||
        String base64_encode(uint8_t * data, size_t length);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* WEBSOCKETS_H_ */
 | 
			
		||||
@@ -1,506 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file WebSocketsClient.cpp
 | 
			
		||||
 * @date 20.05.2015
 | 
			
		||||
 * @author Markus Sattler
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2015 Markus Sattler. All rights reserved.
 | 
			
		||||
 * This file is part of the WebSockets for Arduino.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2.1 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "WebSockets.h"
 | 
			
		||||
#include "WebSocketsClient.h"
 | 
			
		||||
 | 
			
		||||
WebSocketsClient::WebSocketsClient() {
 | 
			
		||||
    _cbEvent = NULL;
 | 
			
		||||
    _client.num = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WebSocketsClient::~WebSocketsClient() {
 | 
			
		||||
    disconnect();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * calles to init the Websockets server
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::begin(const char *host, uint16_t port, const char * url) {
 | 
			
		||||
    _host = host;
 | 
			
		||||
    _port = port;
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
    _fingerprint = "";
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    _client.num = 0;
 | 
			
		||||
    _client.status = WSC_NOT_CONNECTED;
 | 
			
		||||
    _client.tcp = NULL;
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
    _client.isSSL = false;
 | 
			
		||||
    _client.ssl = NULL;
 | 
			
		||||
#endif
 | 
			
		||||
    _client.cUrl = url;
 | 
			
		||||
    _client.cCode = 0;
 | 
			
		||||
    _client.cIsUpgrade = false;
 | 
			
		||||
    _client.cIsWebsocket = true;
 | 
			
		||||
    _client.cKey = "";
 | 
			
		||||
    _client.cAccept = "";
 | 
			
		||||
    _client.cProtocol = "";
 | 
			
		||||
    _client.cExtensions = "";
 | 
			
		||||
    _client.cVersion = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
    randomSeed(RANDOM_REG32);
 | 
			
		||||
#else
 | 
			
		||||
    // todo find better seed
 | 
			
		||||
    randomSeed(millis());
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsClient::begin(String host, uint16_t port, String url) {
 | 
			
		||||
    begin(host.c_str(), port, url.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
void WebSocketsClient::beginSSL(const char *host, uint16_t port, const char * url, const char * fingerprint) {
 | 
			
		||||
    begin(host, port, url);
 | 
			
		||||
    _client.isSSL = true;
 | 
			
		||||
    _fingerprint = fingerprint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsClient::beginSSL(String host, uint16_t port, String url, String fingerprint) {
 | 
			
		||||
    beginSSL(host.c_str(), port, url.c_str(), fingerprint.c_str());
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * called in arduino loop
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::loop(void) {
 | 
			
		||||
    if(!clientIsConnected(&_client)) {
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
        if(_client.isSSL) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Client] connect wss...\n");
 | 
			
		||||
            if(_client.ssl) {
 | 
			
		||||
                delete _client.ssl;
 | 
			
		||||
                _client.ssl = NULL;
 | 
			
		||||
                _client.tcp = NULL;
 | 
			
		||||
            }
 | 
			
		||||
            _client.ssl = new WiFiClientSecure();
 | 
			
		||||
            _client.tcp = _client.ssl;
 | 
			
		||||
        } else {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Client] connect ws...\n");
 | 
			
		||||
            if(_client.tcp) {
 | 
			
		||||
                delete _client.tcp;
 | 
			
		||||
                _client.tcp = NULL;
 | 
			
		||||
            }
 | 
			
		||||
            _client.tcp = new WiFiClient();
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
        _client.tcp = new WEBSOCKETS_NETWORK_CLASS();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        if(!_client.tcp) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(_client.tcp->connect(_host.c_str(), _port)) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Client] connected to %s:%u.\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(_host.c_str());
 | 
			
		||||
	//DEBUG_WEBSOCKETS(_port);
 | 
			
		||||
 | 
			
		||||
            _client.status = WSC_HEADER;
 | 
			
		||||
 | 
			
		||||
            // set Timeout for readBytesUntil and readStringUntil
 | 
			
		||||
            _client.tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
            _client.tcp->setNoDelay(true);
 | 
			
		||||
 | 
			
		||||
            if(_client.isSSL && _fingerprint.length()) {
 | 
			
		||||
                if(!_client.ssl->verify(_fingerprint.c_str(), _host.c_str())) {
 | 
			
		||||
                    DEBUG_WEBSOCKETS("[WS-Client] certificate mismatch\n");
 | 
			
		||||
                    WebSockets::clientDisconnect(&_client, 1000);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            // send Header to Server
 | 
			
		||||
            sendHeader(&_client);
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Client] connection to %s:%u Faild\n");
 | 
			
		||||
	///EBUG_WEBSOCKETS(_host.c_str());
 | 
			
		||||
	//DEBUG_WEBSOCKETS(_port);
 | 
			
		||||
            delay(10); //some litle delay to not flood the server
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        handleClientData();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * set callback function
 | 
			
		||||
 * @param cbEvent WebSocketServerEvent
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::onEvent(WebSocketClientEvent cbEvent) {
 | 
			
		||||
    _cbEvent = cbEvent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * send text data to client
 | 
			
		||||
 * @param num uint8_t client id
 | 
			
		||||
 * @param payload uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @param headerToPayload bool  (see sendFrame for more details)
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::sendTXT(uint8_t * payload, size_t length, bool headerToPayload) {
 | 
			
		||||
    if(length == 0) {
 | 
			
		||||
        length = strlen((const char *) payload);
 | 
			
		||||
    }
 | 
			
		||||
    if(clientIsConnected(&_client)) {
 | 
			
		||||
        sendFrame(&_client, WSop_text, payload, length, true, true, headerToPayload);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsClient::sendTXT(const uint8_t * payload, size_t length) {
 | 
			
		||||
    sendTXT((uint8_t *) payload, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsClient::sendTXT(char * payload, size_t length, bool headerToPayload) {
 | 
			
		||||
    sendTXT((uint8_t *) payload, length, headerToPayload);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsClient::sendTXT(const char * payload, size_t length) {
 | 
			
		||||
    sendTXT((uint8_t *) payload, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsClient::sendTXT(String payload) {
 | 
			
		||||
    sendTXT((uint8_t *) payload.c_str(), payload.length());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * send binary data to client
 | 
			
		||||
 * @param num uint8_t client id
 | 
			
		||||
 * @param payload uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @param headerToPayload bool  (see sendFrame for more details)
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::sendBIN(uint8_t * payload, size_t length, bool headerToPayload) {
 | 
			
		||||
    if(clientIsConnected(&_client)) {
 | 
			
		||||
        sendFrame(&_client, WSop_binary, payload, length, true, true, headerToPayload);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsClient::sendBIN(const uint8_t * payload, size_t length) {
 | 
			
		||||
    sendBIN((uint8_t *) payload, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * disconnect one client
 | 
			
		||||
 * @param num uint8_t client id
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::disconnect(void) {
 | 
			
		||||
    if(clientIsConnected(&_client)) {
 | 
			
		||||
        WebSockets::clientDisconnect(&_client, 1000);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//#################################################################################
 | 
			
		||||
//#################################################################################
 | 
			
		||||
//#################################################################################
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 * @param opcode WSopcode_t
 | 
			
		||||
 * @param payload  uint8_t *
 | 
			
		||||
 * @param lenght size_t
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::messageRecived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t lenght) {
 | 
			
		||||
    WStype_t type = WStype_ERROR;
 | 
			
		||||
 | 
			
		||||
    switch(opcode) {
 | 
			
		||||
        case WSop_text:
 | 
			
		||||
            type = WStype_TEXT;
 | 
			
		||||
            break;
 | 
			
		||||
        case WSop_binary:
 | 
			
		||||
            type = WStype_BIN;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    runCbEvent(type, payload, lenght);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Disconnect an client
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::clientDisconnect(WSclient_t * client) {
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
    if(client->isSSL && client->ssl) {
 | 
			
		||||
        if(client->ssl->connected()) {
 | 
			
		||||
            client->ssl->flush();
 | 
			
		||||
            client->ssl->stop();
 | 
			
		||||
        }
 | 
			
		||||
        delete client->ssl;
 | 
			
		||||
        client->ssl = NULL;
 | 
			
		||||
        client->tcp = NULL;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if(client->tcp) {
 | 
			
		||||
        if(client->tcp->connected()) {
 | 
			
		||||
            client->tcp->flush();
 | 
			
		||||
            client->tcp->stop();
 | 
			
		||||
        }
 | 
			
		||||
        delete client->tcp;
 | 
			
		||||
        client->tcp = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    client->cCode = 0;
 | 
			
		||||
    client->cKey = "";
 | 
			
		||||
    client->cAccept = "";
 | 
			
		||||
    client->cProtocol = "";
 | 
			
		||||
    client->cVersion = 0;
 | 
			
		||||
    client->cIsUpgrade = false;
 | 
			
		||||
    client->cIsWebsocket = false;
 | 
			
		||||
 | 
			
		||||
    client->status = WSC_NOT_CONNECTED;
 | 
			
		||||
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS-Client] client disconnected.\n");
 | 
			
		||||
 | 
			
		||||
    runCbEvent(WStype_DISCONNECTED, NULL, 0);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * get client state
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 * @return true = conneted
 | 
			
		||||
 */
 | 
			
		||||
bool WebSocketsClient::clientIsConnected(WSclient_t * client) {
 | 
			
		||||
 | 
			
		||||
    if(!client->tcp) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(client->tcp->connected()) {
 | 
			
		||||
        if(client->status != WSC_NOT_CONNECTED) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        // client lost
 | 
			
		||||
        if(client->status != WSC_NOT_CONNECTED) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Client] connection lost.\n");
 | 
			
		||||
            // do cleanup
 | 
			
		||||
            clientDisconnect(client);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(client->tcp) {
 | 
			
		||||
        // do cleanup
 | 
			
		||||
        clientDisconnect(client);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handel incomming data from Client
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::handleClientData(void) {
 | 
			
		||||
    int len = _client.tcp->available();
 | 
			
		||||
    if(len > 0) {
 | 
			
		||||
        switch(_client.status) {
 | 
			
		||||
            case WSC_HEADER:
 | 
			
		||||
                handleHeader(&_client);
 | 
			
		||||
                break;
 | 
			
		||||
            case WSC_CONNECTED:
 | 
			
		||||
                WebSockets::handleWebsocket(&_client);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                WebSockets::clientDisconnect(&_client, 1002);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
    delay(0);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * send the WebSocket header to Server
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::sendHeader(WSclient_t * client) {
 | 
			
		||||
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS-Client][sendHeader] sending header...\n");
 | 
			
		||||
 | 
			
		||||
    uint8_t randomKey[16] = { 0 };
 | 
			
		||||
 | 
			
		||||
    for(uint8_t i = 0; i < sizeof(randomKey); i++) {
 | 
			
		||||
        randomKey[i] = random(0xFF);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    client->cKey = base64_encode(&randomKey[0], 16);
 | 
			
		||||
 | 
			
		||||
#ifndef NODEBUG_WEBSOCKETS
 | 
			
		||||
    unsigned long start = micros();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    String handshake =  "GET " + client->cUrl + " HTTP/1.1\r\n"
 | 
			
		||||
                        "Host: " + _host + "\r\n"
 | 
			
		||||
                        "Upgrade: websocket\r\n"
 | 
			
		||||
                        "Connection: Upgrade\r\n"
 | 
			
		||||
                        "User-Agent: arduino-WebSocket-Client\r\n"
 | 
			
		||||
                        "Sec-WebSocket-Version: 13\r\n"
 | 
			
		||||
                        "Sec-WebSocket-Protocol: arduino\r\n"
 | 
			
		||||
                        "Sec-WebSocket-Key: " + client->cKey + "\r\n";
 | 
			
		||||
 | 
			
		||||
    if(client->cExtensions.length() > 0) {
 | 
			
		||||
        handshake += "Sec-WebSocket-Extensions: " + client->cExtensions + "\r\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handshake += "\r\n";
 | 
			
		||||
 | 
			
		||||
    client->tcp->write(handshake.c_str(), handshake.length());
 | 
			
		||||
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS-Client][sendHeader] sending header... Done (%uus).\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS((micros() - start));
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * handle the WebSocket header reading
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsClient::handleHeader(WSclient_t * client) {
 | 
			
		||||
 | 
			
		||||
    String headerLine = client->tcp->readStringUntil('\n');
 | 
			
		||||
    headerLine.trim(); // remove \r
 | 
			
		||||
 | 
			
		||||
    if(headerLine.length() > 0) {
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] RX: %s\n");
 | 
			
		||||
	DEBUG_WEBSOCKETS(headerLine.c_str());
 | 
			
		||||
 | 
			
		||||
        if(headerLine.startsWith("HTTP/1.")) {
 | 
			
		||||
            // "HTTP/1.1 101 Switching Protocols"
 | 
			
		||||
            client->cCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
 | 
			
		||||
        } else if(headerLine.indexOf(':')) {
 | 
			
		||||
            String headerName = headerLine.substring(0, headerLine.indexOf(':'));
 | 
			
		||||
            String headerValue = headerLine.substring(headerLine.indexOf(':') + 2);
 | 
			
		||||
 | 
			
		||||
            if(headerName.equalsIgnoreCase("Connection")) {
 | 
			
		||||
                if(headerValue.indexOf("Upgrade") >= 0) {
 | 
			
		||||
                    client->cIsUpgrade = true;
 | 
			
		||||
                }
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Upgrade")) {
 | 
			
		||||
                if(headerValue.equalsIgnoreCase("websocket")) {
 | 
			
		||||
                    client->cIsWebsocket = true;
 | 
			
		||||
                }
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Sec-WebSocket-Accept")) {
 | 
			
		||||
                client->cAccept = headerValue;
 | 
			
		||||
                client->cAccept.trim(); // see rfc6455
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Sec-WebSocket-Protocol")) {
 | 
			
		||||
                client->cProtocol = headerValue;
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Sec-WebSocket-Extensions")) {
 | 
			
		||||
                client->cExtensions = headerValue;
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Sec-WebSocket-Version")) {
 | 
			
		||||
                client->cVersion = headerValue.toInt();
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header error (%s)\n");
 | 
			
		||||
			DEBUG_WEBSOCKETS(headerLine.c_str());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header read fin.\n");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Client settings:\n");
 | 
			
		||||
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cURL: %s\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cUrl.c_str());
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cKey: %s\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cKey.c_str());
 | 
			
		||||
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Server header:\n");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cCode: %d\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cCode);
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cIsUpgrade: %d\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cIsUpgrade);
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cIsWebsocket: %d\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cIsWebsocket);
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cAccept: %s\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cAccept.c_str());
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cProtocol: %s\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cProtocol.c_str());
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cExtensions: %s\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cExtensions.c_str());
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cVersion: %d\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cVersion);
 | 
			
		||||
 | 
			
		||||
        bool ok = (client->cIsUpgrade && client->cIsWebsocket);
 | 
			
		||||
 | 
			
		||||
        if(ok) {
 | 
			
		||||
            switch(client->cCode) {
 | 
			
		||||
                case 101:  ///< Switching Protocols
 | 
			
		||||
 | 
			
		||||
                    break;
 | 
			
		||||
                case 403: ///< Forbidden
 | 
			
		||||
                    // todo handle login
 | 
			
		||||
                default:   ///< Server dont unterstand requrst
 | 
			
		||||
                    ok = false;
 | 
			
		||||
                    DEBUG_WEBSOCKETS("[WS-Client][handleHeader] serverCode is not 101 (%d)\n");
 | 
			
		||||
	//DEBUG_WEBSOCKETS(client->cCode);
 | 
			
		||||
                    clientDisconnect(client);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(ok) {
 | 
			
		||||
            if(client->cAccept.length() == 0) {
 | 
			
		||||
                ok = false;
 | 
			
		||||
            } else {
 | 
			
		||||
                // generate Sec-WebSocket-Accept key for check
 | 
			
		||||
                String sKey = acceptKey(client->cKey);
 | 
			
		||||
                if(sKey != client->cAccept) {
 | 
			
		||||
                    DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Sec-WebSocket-Accept is wrong\n");
 | 
			
		||||
                    ok = false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(ok) {
 | 
			
		||||
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Websocket connection init done.\n");
 | 
			
		||||
 | 
			
		||||
            client->status = WSC_CONNECTED;
 | 
			
		||||
 | 
			
		||||
            runCbEvent(WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length());
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");
 | 
			
		||||
            client->tcp->write("This is a webSocket client!");
 | 
			
		||||
            clientDisconnect(client);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,98 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file WebSocketsClient.h
 | 
			
		||||
 * @date 20.05.2015
 | 
			
		||||
 * @author Markus Sattler
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2015 Markus Sattler. All rights reserved.
 | 
			
		||||
 * This file is part of the WebSockets for Arduino.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2.1 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef WEBSOCKETSCLIENT_H_
 | 
			
		||||
#define WEBSOCKETSCLIENT_H_
 | 
			
		||||
 | 
			
		||||
#include <Arduino.h>
 | 
			
		||||
#include "WebSockets.h"
 | 
			
		||||
 | 
			
		||||
class WebSocketsClient: private WebSockets {
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
        typedef void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length);
 | 
			
		||||
 | 
			
		||||
        WebSocketsClient(void);
 | 
			
		||||
        ~WebSocketsClient(void);
 | 
			
		||||
 | 
			
		||||
        void begin(const char *host, uint16_t port, const char * url = "/");
 | 
			
		||||
        void begin(String host, uint16_t port, String url = "/");
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
        void beginSSL(const char *host, uint16_t port, const char * url = "/", const char * = "");
 | 
			
		||||
        void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        void loop(void);
 | 
			
		||||
 | 
			
		||||
        void onEvent(WebSocketClientEvent cbEvent);
 | 
			
		||||
 | 
			
		||||
        void sendTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false);
 | 
			
		||||
        void sendTXT(const uint8_t * payload, size_t length = 0);
 | 
			
		||||
        void sendTXT(char * payload, size_t length = 0, bool headerToPayload = false);
 | 
			
		||||
        void sendTXT(const char * payload, size_t length = 0);
 | 
			
		||||
        void sendTXT(String payload);
 | 
			
		||||
 | 
			
		||||
        void sendBIN(uint8_t * payload, size_t length, bool headerToPayload = false);
 | 
			
		||||
        void sendBIN(const uint8_t * payload, size_t length);
 | 
			
		||||
 | 
			
		||||
        void disconnect(void);
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        String _host;
 | 
			
		||||
        uint16_t _port;
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
        String _fingerprint;
 | 
			
		||||
#endif
 | 
			
		||||
        WSclient_t _client;
 | 
			
		||||
 | 
			
		||||
        WebSocketClientEvent _cbEvent;
 | 
			
		||||
 | 
			
		||||
        void messageRecived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
 | 
			
		||||
 | 
			
		||||
        void clientDisconnect(WSclient_t * client);
 | 
			
		||||
        bool clientIsConnected(WSclient_t * client);
 | 
			
		||||
 | 
			
		||||
        void handleNewClients(void);
 | 
			
		||||
        void handleClientData(void);
 | 
			
		||||
 | 
			
		||||
        void sendHeader(WSclient_t * client);
 | 
			
		||||
        void handleHeader(WSclient_t * client);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * called for sending a Event to the app
 | 
			
		||||
         * @param type WStype_t
 | 
			
		||||
         * @param payload uint8_t *
 | 
			
		||||
         * @param length size_t
 | 
			
		||||
         */
 | 
			
		||||
        virtual void runCbEvent(WStype_t type, uint8_t * payload, size_t length) {
 | 
			
		||||
            if(_cbEvent) {
 | 
			
		||||
                _cbEvent(type, payload, length);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* WEBSOCKETSCLIENT_H_ */
 | 
			
		||||
@@ -1,714 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file WebSocketsServer.cpp
 | 
			
		||||
 * @date 20.05.2015
 | 
			
		||||
 * @author Markus Sattler
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2015 Markus Sattler. All rights reserved.
 | 
			
		||||
 * This file is part of the WebSockets for Arduino.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2.1 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "WebSockets.h"
 | 
			
		||||
#include "WebSocketsServer.h"
 | 
			
		||||
 | 
			
		||||
WebSocketsServer::WebSocketsServer(uint16_t port) {
 | 
			
		||||
    _port = port;
 | 
			
		||||
    _server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port);
 | 
			
		||||
 | 
			
		||||
    _cbEvent = NULL;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WebSocketsServer::~WebSocketsServer() {
 | 
			
		||||
    // disconnect all clients
 | 
			
		||||
    disconnect();
 | 
			
		||||
 | 
			
		||||
    // TODO how to close server?
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * calles to init the Websockets server
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::begin(void) {
 | 
			
		||||
    WSclient_t * client;
 | 
			
		||||
 | 
			
		||||
    // init client storage
 | 
			
		||||
    for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
 | 
			
		||||
        client = &_clients[i];
 | 
			
		||||
 | 
			
		||||
        client->num = i;
 | 
			
		||||
        client->status = WSC_NOT_CONNECTED;
 | 
			
		||||
        client->tcp = NULL;
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
        client->isSSL = false;
 | 
			
		||||
        client->ssl = NULL;
 | 
			
		||||
#endif
 | 
			
		||||
        client->cUrl = "";
 | 
			
		||||
        client->cCode = 0;
 | 
			
		||||
        client->cKey = "";
 | 
			
		||||
        client->cProtocol = "";
 | 
			
		||||
        client->cVersion = 0;
 | 
			
		||||
        client->cIsUpgrade = false;
 | 
			
		||||
        client->cIsWebsocket = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
    randomSeed(RANDOM_REG32);
 | 
			
		||||
#else
 | 
			
		||||
    // TODO find better seed
 | 
			
		||||
    randomSeed(millis());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    _server->begin();
 | 
			
		||||
 | 
			
		||||
    DEBUG_WEBSOCKETS("[WS-Server] Server Started.\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * called in arduino loop
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::loop(void) {
 | 
			
		||||
    handleNewClients();
 | 
			
		||||
    handleClientData();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * set callback function
 | 
			
		||||
 * @param cbEvent WebSocketServerEvent
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::onEvent(WebSocketServerEvent cbEvent) {
 | 
			
		||||
    _cbEvent = cbEvent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * send text data to client
 | 
			
		||||
 * @param num uint8_t client id
 | 
			
		||||
 * @param payload uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @param headerToPayload bool  (see sendFrame for more details)
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
 | 
			
		||||
    if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if(length == 0) {
 | 
			
		||||
        length = strlen((const char *) payload);
 | 
			
		||||
    }
 | 
			
		||||
    WSclient_t * client = &_clients[num];
 | 
			
		||||
    if(clientIsConnected(client)) {
 | 
			
		||||
        sendFrame(client, WSop_text, payload, length, false, true, headerToPayload);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::sendTXT(uint8_t num, const uint8_t * payload, size_t length) {
 | 
			
		||||
    sendTXT(num, (uint8_t *) payload, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::sendTXT(uint8_t num, char * payload, size_t length, bool headerToPayload) {
 | 
			
		||||
    sendTXT(num, (uint8_t *) payload, length, headerToPayload);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::sendTXT(uint8_t num, const char * payload, size_t length) {
 | 
			
		||||
    sendTXT(num, (uint8_t *) payload, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::sendTXT(uint8_t num, String payload) {
 | 
			
		||||
    sendTXT(num, (uint8_t *) payload.c_str(), payload.length());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * send text data to client all
 | 
			
		||||
 * @param payload uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @param headerToPayload bool  (see sendFrame for more details)
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length, bool headerToPayload) {
 | 
			
		||||
    WSclient_t * client;
 | 
			
		||||
    if(length == 0) {
 | 
			
		||||
        length = strlen((const char *) payload);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
 | 
			
		||||
        client = &_clients[i];
 | 
			
		||||
        if(clientIsConnected(client)) {
 | 
			
		||||
            sendFrame(client, WSop_text, payload, length, false, true, headerToPayload);
 | 
			
		||||
        }
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
        delay(0);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::broadcastTXT(const uint8_t * payload, size_t length) {
 | 
			
		||||
    broadcastTXT((uint8_t *) payload, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::broadcastTXT(char * payload, size_t length, bool headerToPayload) {
 | 
			
		||||
    broadcastTXT((uint8_t *) payload, length, headerToPayload);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::broadcastTXT(const char * payload, size_t length) {
 | 
			
		||||
    broadcastTXT((uint8_t *) payload, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::broadcastTXT(String payload) {
 | 
			
		||||
    broadcastTXT((uint8_t *) payload.c_str(), payload.length());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * send binary data to client
 | 
			
		||||
 * @param num uint8_t client id
 | 
			
		||||
 * @param payload uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @param headerToPayload bool  (see sendFrame for more details)
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
 | 
			
		||||
    if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    WSclient_t * client = &_clients[num];
 | 
			
		||||
    if(clientIsConnected(client)) {
 | 
			
		||||
        sendFrame(client, WSop_binary, payload, length, false, true, headerToPayload);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::sendBIN(uint8_t num, const uint8_t * payload, size_t length) {
 | 
			
		||||
    sendBIN(num, (uint8_t *) payload, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * send binary data to client all
 | 
			
		||||
 * @param payload uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @param headerToPayload bool  (see sendFrame for more details)
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload) {
 | 
			
		||||
    WSclient_t * client;
 | 
			
		||||
    for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
 | 
			
		||||
        client = &_clients[i];
 | 
			
		||||
        if(clientIsConnected(client)) {
 | 
			
		||||
            sendFrame(client, WSop_binary, payload, length, false, true, headerToPayload);
 | 
			
		||||
        }
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
        delay(0);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebSocketsServer::broadcastBIN(const uint8_t * payload, size_t length) {
 | 
			
		||||
    broadcastBIN((uint8_t *) payload, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sends a WS ping to Client
 | 
			
		||||
 * @param num uint8_t client id
 | 
			
		||||
 * @param payload uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @return true if ping is send out
 | 
			
		||||
 */
 | 
			
		||||
bool WebSocketsServer::sendPing(uint8_t num, uint8_t * payload, size_t length) {
 | 
			
		||||
    if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    WSclient_t * client;
 | 
			
		||||
    client = &_clients[num];
 | 
			
		||||
    if(clientIsConnected(client)) {
 | 
			
		||||
        return sendFrame(client, WSop_ping, payload, length);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool WebSocketsServer::sendPing(uint8_t num, String & payload) {
 | 
			
		||||
    return sendPing(num, (uint8_t *) payload.c_str(), payload.length());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  sends a WS ping to all Client
 | 
			
		||||
 * @param payload uint8_t *
 | 
			
		||||
 * @param length size_t
 | 
			
		||||
 * @return true if ping is send out
 | 
			
		||||
 */
 | 
			
		||||
bool WebSocketsServer::broadcastPing(uint8_t * payload, size_t length) {
 | 
			
		||||
    WSclient_t * client;
 | 
			
		||||
    bool ret = true;
 | 
			
		||||
    for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
 | 
			
		||||
        client = &_clients[i];
 | 
			
		||||
        if(clientIsConnected(client)) {
 | 
			
		||||
            if(!sendFrame(client, WSop_ping, payload, length)) {
 | 
			
		||||
                ret = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
        delay(0);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool WebSocketsServer::broadcastPing(String & payload) {
 | 
			
		||||
    return broadcastPing((uint8_t *) payload.c_str(), payload.length());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool WebSocketsServer::clientConnected(uint8_t num) {
 | 
			
		||||
    WSclient_t * client;
 | 
			
		||||
    client = &_clients[num];
 | 
			
		||||
    return clientIsConnected(client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * disconnect all clients
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::disconnect(void) {
 | 
			
		||||
    WSclient_t * client;
 | 
			
		||||
    for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
 | 
			
		||||
        client = &_clients[i];
 | 
			
		||||
        if(clientIsConnected(client)) {
 | 
			
		||||
            WebSockets::clientDisconnect(client, 1000);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * disconnect one client
 | 
			
		||||
 * @param num uint8_t client id
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::disconnect(uint8_t num) {
 | 
			
		||||
    if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    WSclient_t * client = &_clients[num];
 | 
			
		||||
    if(clientIsConnected(client)) {
 | 
			
		||||
        WebSockets::clientDisconnect(client, 1000);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
/**
 | 
			
		||||
 * get an IP for a client
 | 
			
		||||
 * @param num uint8_t client id
 | 
			
		||||
 * @return IPAddress
 | 
			
		||||
 */
 | 
			
		||||
IPAddress WebSocketsServer::remoteIP(uint8_t num) {
 | 
			
		||||
    if(num < WEBSOCKETS_SERVER_CLIENT_MAX) {
 | 
			
		||||
        WSclient_t * client = &_clients[num];
 | 
			
		||||
        if(clientIsConnected(client)) {
 | 
			
		||||
            return client->tcp->remoteIP();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return IPAddress();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//#################################################################################
 | 
			
		||||
//#################################################################################
 | 
			
		||||
//#################################################################################
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 * @param opcode WSopcode_t
 | 
			
		||||
 * @param payload  uint8_t *
 | 
			
		||||
 * @param lenght size_t
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::messageRecived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t lenght) {
 | 
			
		||||
    WStype_t type = WStype_ERROR;
 | 
			
		||||
 | 
			
		||||
    switch(opcode) {
 | 
			
		||||
        case WSop_text:
 | 
			
		||||
            type = WStype_TEXT;
 | 
			
		||||
            break;
 | 
			
		||||
        case WSop_binary:
 | 
			
		||||
            type = WStype_BIN;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    runCbEvent(client->num, type, payload, lenght);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Disconnect an client
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::clientDisconnect(WSclient_t * client) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
    if(client->isSSL && client->ssl) {
 | 
			
		||||
        if(client->ssl->connected()) {
 | 
			
		||||
            client->ssl->flush();
 | 
			
		||||
            client->ssl->stop();
 | 
			
		||||
        }
 | 
			
		||||
        delete client->ssl;
 | 
			
		||||
        client->ssl = NULL;
 | 
			
		||||
        client->tcp = NULL;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if(client->tcp) {
 | 
			
		||||
        if(client->tcp->connected()) {
 | 
			
		||||
            client->tcp->flush();
 | 
			
		||||
            client->tcp->stop();
 | 
			
		||||
        }
 | 
			
		||||
        delete client->tcp;
 | 
			
		||||
        client->tcp = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    client->cUrl = "";
 | 
			
		||||
    client->cKey = "";
 | 
			
		||||
    client->cProtocol = "";
 | 
			
		||||
    client->cVersion = 0;
 | 
			
		||||
    client->cIsUpgrade = false;
 | 
			
		||||
    client->cIsWebsocket = false;
 | 
			
		||||
 | 
			
		||||
    client->status = WSC_NOT_CONNECTED;
 | 
			
		||||
 | 
			
		||||
	DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
    DEBUG_WEBSOCKETS(" client disconnected.\n");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    runCbEvent(client->num, WStype_DISCONNECTED, NULL, 0);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * get client state
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 * @return true = conneted
 | 
			
		||||
 */
 | 
			
		||||
bool WebSocketsServer::clientIsConnected(WSclient_t * client) {
 | 
			
		||||
 | 
			
		||||
    if(!client->tcp) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(client->tcp->connected()) {
 | 
			
		||||
        if(client->status != WSC_NOT_CONNECTED) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        // client lost
 | 
			
		||||
		DEBUG_WEBSOCKETS(client->status);
 | 
			
		||||
        if(client->status != WSC_NOT_CONNECTED) {
 | 
			
		||||
			DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
			DEBUG_WEBSOCKETS(" client connection lost.\n");
 | 
			
		||||
 | 
			
		||||
            // do cleanup
 | 
			
		||||
            clientDisconnect(client);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(client->tcp) {
 | 
			
		||||
        // do cleanup
 | 
			
		||||
        clientDisconnect(client);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266)
 | 
			
		||||
  bool WebSocketsServer::clientExists(const WEBSOCKETS_NETWORK_CLASS &c)
 | 
			
		||||
  {
 | 
			
		||||
	WSclient_t * client;
 | 
			
		||||
    for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
 | 
			
		||||
	  client = &_clients[i];
 | 
			
		||||
      if (clientIsConnected(client) && (*client->tcp == c))
 | 
			
		||||
        return true;
 | 
			
		||||
	}
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handle incomming Connection Request
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::handleNewClients(void) {
 | 
			
		||||
    WSclient_t * client;
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
    while(_server->hasClient()) {
 | 
			
		||||
#endif                         
 | 
			
		||||
        bool ok = false;
 | 
			
		||||
        // search free list entry for client
 | 
			
		||||
        for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
 | 
			
		||||
            client = &_clients[i];
 | 
			
		||||
 | 
			
		||||
            // state is not connected or tcp connection is lost
 | 
			
		||||
            if(!clientIsConnected(client)) {
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
                // store new connection
 | 
			
		||||
                client->tcp = new WEBSOCKETS_NETWORK_CLASS(_server->available());
 | 
			
		||||
#else
 | 
			
		||||
				WEBSOCKETS_NETWORK_CLASS newClient = _server->available();
 | 
			
		||||
				if (newClient && !clientExists(newClient)) {
 | 
			
		||||
					client->tcp = new WEBSOCKETS_NETWORK_CLASS(newClient);
 | 
			
		||||
				} else {
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
				//if (!client->tcp->connected() || !client->tcp->available()) {
 | 
			
		||||
				//	DEBUG_WEBSOCKETS("[WS-Client] Not Connected!\n");
 | 
			
		||||
				//	return;
 | 
			
		||||
				//}
 | 
			
		||||
#endif
 | 
			
		||||
                if(!client->tcp) {
 | 
			
		||||
                    DEBUG_WEBSOCKETS("[WS-Server] creating Network class failed!");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
                client->isSSL = false;
 | 
			
		||||
                client->tcp->setNoDelay(true);
 | 
			
		||||
#endif
 | 
			
		||||
                // set Timeout for readBytesUntil and readStringUntil
 | 
			
		||||
                client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
 | 
			
		||||
                client->status = WSC_HEADER;
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
                IPAddress ip = client->tcp->remoteIP();
 | 
			
		||||
                DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
				DEBUG_WEBSOCKETS(" new client from %d.%d.%d.%d\n");
 | 
			
		||||
 | 
			
		||||
				//DEBUG_WEBSOCKETS(ip[0]);
 | 
			
		||||
				//DEBUG_WEBSOCKETS(ip[1]);
 | 
			
		||||
				//DEBUG_WEBSOCKETS(ip[2]);
 | 
			
		||||
				//DEBUG_WEBSOCKETS(ip[3]);
 | 
			
		||||
#else
 | 
			
		||||
                DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
				DEBUG_WEBSOCKETS(" new client\n");
 | 
			
		||||
#endif
 | 
			
		||||
                ok = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!ok) {
 | 
			
		||||
            // no free space to handle client
 | 
			
		||||
            WEBSOCKETS_NETWORK_CLASS tcpClient = _server->available();
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
            IPAddress ip = client->tcp->remoteIP();
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Server] no free space new client from %d.%d.%d.%d\n");
 | 
			
		||||
			//DEBUG_WEBSOCKETS(ip[0]);
 | 
			
		||||
			//DEBUG_WEBSOCKETS(ip[1]);
 | 
			
		||||
			//DEBUG_WEBSOCKETS(ip[2]);
 | 
			
		||||
			//DEBUG_WEBSOCKETS(ip[3]);
 | 
			
		||||
#else
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Server] no free space new client\n");
 | 
			
		||||
#endif
 | 
			
		||||
            tcpClient.stop();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
        delay(0);
 | 
			
		||||
#endif
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handel incomming data from Client
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::handleClientData(void) {
 | 
			
		||||
 | 
			
		||||
    WSclient_t * client;
 | 
			
		||||
    for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
 | 
			
		||||
        client = &_clients[i];
 | 
			
		||||
        if(clientIsConnected(client)) {
 | 
			
		||||
            int len = client->tcp->available();
 | 
			
		||||
            if(len > 0) {
 | 
			
		||||
                switch(client->status) {
 | 
			
		||||
                    case WSC_HEADER:
 | 
			
		||||
                        handleHeader(client);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case WSC_CONNECTED:
 | 
			
		||||
                        WebSockets::handleWebsocket(client);
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        WebSockets::clientDisconnect(client, 1002);
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#ifdef ESP8266
 | 
			
		||||
        delay(0);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * handle the WebSocket header reading
 | 
			
		||||
 * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
 */
 | 
			
		||||
void WebSocketsServer::handleHeader(WSclient_t * client) {
 | 
			
		||||
 | 
			
		||||
    String headerLine = client->tcp->readStringUntil('\n');
 | 
			
		||||
    headerLine.trim(); // remove \r
 | 
			
		||||
 | 
			
		||||
    if(headerLine.length() > 0) {
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[handleHeader] RX: ");
 | 
			
		||||
		DEBUG_WEBSOCKETS(headerLine.c_str());
 | 
			
		||||
		DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
        // websocket request starts allways with GET see rfc6455
 | 
			
		||||
        if(headerLine.startsWith("GET ")) {
 | 
			
		||||
            // cut URL out
 | 
			
		||||
            client->cUrl = headerLine.substring(4, headerLine.indexOf(' ', 4));
 | 
			
		||||
        } else if(headerLine.indexOf(':')) {
 | 
			
		||||
            String headerName = headerLine.substring(0, headerLine.indexOf(':'));
 | 
			
		||||
            String headerValue = headerLine.substring(headerLine.indexOf(':') + 2);
 | 
			
		||||
            //Serial.print(headerName);  Serial.print(":");  Serial.println(headerValue);
 | 
			
		||||
 | 
			
		||||
            if(headerName.equalsIgnoreCase("Connection")) {
 | 
			
		||||
                if(headerValue.indexOf("Upgrade") >= 0) {
 | 
			
		||||
                    client->cIsUpgrade = true;
 | 
			
		||||
                }
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Upgrade")) {
 | 
			
		||||
                if(headerValue.equalsIgnoreCase("websocket")) {
 | 
			
		||||
                    client->cIsWebsocket = true;
 | 
			
		||||
                }
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Sec-WebSocket-Version")) {
 | 
			
		||||
                client->cVersion = headerValue.toInt();
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Sec-WebSocket-Key")) {
 | 
			
		||||
                client->cKey = headerValue;
 | 
			
		||||
                client->cKey.trim(); // see rfc6455
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Sec-WebSocket-Protocol")) {
 | 
			
		||||
                client->cProtocol = headerValue;
 | 
			
		||||
            } else if(headerName.equalsIgnoreCase("Sec-WebSocket-Extensions")) {
 | 
			
		||||
                client->cExtensions = headerValue;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            Serial.print("[WS-Client][handleHeader] Header error (%s)\n");
 | 
			
		||||
			Serial.print(headerLine.c_str());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
		DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[handleHeader] Header read fin.\n");
 | 
			
		||||
	
 | 
			
		||||
		DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[handleHeader]  - cURL: ");
 | 
			
		||||
		DEBUG_WEBSOCKETS(client->cUrl.c_str());
 | 
			
		||||
		DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[handleHeader]  - cIsUpgrade: ");
 | 
			
		||||
		DEBUG_WEBSOCKETS(client->cIsUpgrade);
 | 
			
		||||
		DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[handleHeader]  - cIsWebsocket: ");
 | 
			
		||||
		DEBUG_WEBSOCKETS(client->cIsWebsocket);
 | 
			
		||||
		DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[handleHeader]  - cKey: ");
 | 
			
		||||
		DEBUG_WEBSOCKETS(client->cKey.c_str());
 | 
			
		||||
		DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[handleHeader]  - cProtocol: ");
 | 
			
		||||
		DEBUG_WEBSOCKETS(client->cProtocol.c_str());
 | 
			
		||||
		DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[handleHeader]  - cExtensions: ");
 | 
			
		||||
		DEBUG_WEBSOCKETS(client->cExtensions.c_str());
 | 
			
		||||
		DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
        DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
        DEBUG_WEBSOCKETS("[handleHeader]  - cVersion: ");
 | 
			
		||||
		DEBUG_WEBSOCKETS(client->cVersion);
 | 
			
		||||
		DEBUG_WEBSOCKETS("\n\n");
 | 
			
		||||
 | 
			
		||||
        bool ok = (client->cIsUpgrade && client->cIsWebsocket);
 | 
			
		||||
        Serial.println("here0");
 | 
			
		||||
 | 
			
		||||
		if (!client->cIsUpgrade) {
 | 
			
		||||
			DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
			DEBUG_WEBSOCKETS("[handleHeader] Error! Not an Upgrade\n");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!client->cIsWebsocket) {
 | 
			
		||||
			DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
			DEBUG_WEBSOCKETS("[handleHeader] Error! Not a Websocket\n");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        if(ok) {
 | 
			
		||||
            Serial.println("here1");
 | 
			
		||||
			DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
			DEBUG_WEBSOCKETS("[handleHeader] First ok test success.\n");
 | 
			
		||||
 | 
			
		||||
            if(client->cUrl.length() == 0) {
 | 
			
		||||
                Serial.println("here2");
 | 
			
		||||
                ok = false;
 | 
			
		||||
            }
 | 
			
		||||
            if(client->cKey.length() == 0) {
 | 
			
		||||
                Serial.println("here3");
 | 
			
		||||
                ok = false;
 | 
			
		||||
            }
 | 
			
		||||
            if(client->cVersion != 13) {
 | 
			
		||||
                Serial.println("here4");
 | 
			
		||||
                ok = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(ok) {
 | 
			
		||||
            Serial.println("here5");
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
			DEBUG_WEBSOCKETS("[handleHeader] Websocket connection incomming.\n");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            // generate Sec-WebSocket-Accept key
 | 
			
		||||
            String sKey = acceptKey(client->cKey);
 | 
			
		||||
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Server][");DEBUG_WEBSOCKETS(client->num);DEBUG_WEBSOCKETS("]");
 | 
			
		||||
			DEBUG_WEBSOCKETS("[handleHeader]  - sKey: ");
 | 
			
		||||
			DEBUG_WEBSOCKETS(sKey.c_str());
 | 
			
		||||
			DEBUG_WEBSOCKETS("\n");
 | 
			
		||||
 | 
			
		||||
            client->status = WSC_CONNECTED;
 | 
			
		||||
 | 
			
		||||
            client->tcp->write("HTTP/1.1 101 Switching Protocols\r\n"
 | 
			
		||||
                    "Server: arduino-WebSocketsServer\r\n"
 | 
			
		||||
                    "Upgrade: websocket\r\n"
 | 
			
		||||
                    "Connection: Upgrade\r\n"
 | 
			
		||||
                    "Sec-WebSocket-Version: 13\r\n"
 | 
			
		||||
                    "Sec-WebSocket-Accept: ");
 | 
			
		||||
            client->tcp->write(sKey.c_str(), sKey.length());
 | 
			
		||||
            client->tcp->write("\r\n");
 | 
			
		||||
 | 
			
		||||
            if(client->cProtocol.length() > 0) {
 | 
			
		||||
                // TODO add api to set Protocol of Server
 | 
			
		||||
                client->tcp->write("Sec-WebSocket-Protocol: arduino\r\n");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // header end
 | 
			
		||||
            client->tcp->write("\r\n");
 | 
			
		||||
 | 
			
		||||
            // send ping
 | 
			
		||||
            WebSockets::sendFrame(client, WSop_ping);
 | 
			
		||||
 | 
			
		||||
            runCbEvent(client->num, WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length());
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            handleNonWebsocketConnection(client);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,143 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file WebSocketsServer.h
 | 
			
		||||
 * @date 20.05.2015
 | 
			
		||||
 * @author Markus Sattler
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2015 Markus Sattler. All rights reserved.
 | 
			
		||||
 * This file is part of the WebSockets for Arduino.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2.1 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef WEBSOCKETSSERVER_H_
 | 
			
		||||
#define WEBSOCKETSSERVER_H_
 | 
			
		||||
 | 
			
		||||
#include <Arduino.h>
 | 
			
		||||
#include "WebSockets.h"
 | 
			
		||||
 | 
			
		||||
#define WEBSOCKETS_SERVER_CLIENT_MAX  (5)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class WebSocketsServer: private WebSockets {
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
        typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length);
 | 
			
		||||
 | 
			
		||||
        WebSocketsServer(uint16_t port);
 | 
			
		||||
        ~WebSocketsServer(void);
 | 
			
		||||
 | 
			
		||||
        void begin(void);
 | 
			
		||||
        void loop(void);
 | 
			
		||||
 | 
			
		||||
        void onEvent(WebSocketServerEvent cbEvent);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0, bool headerToPayload = false);
 | 
			
		||||
        void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
 | 
			
		||||
        void sendTXT(uint8_t num, char * payload, size_t length = 0, bool headerToPayload = false);
 | 
			
		||||
        void sendTXT(uint8_t num, const char * payload, size_t length = 0);
 | 
			
		||||
        void sendTXT(uint8_t num, String payload);
 | 
			
		||||
 | 
			
		||||
        void broadcastTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false);
 | 
			
		||||
        void broadcastTXT(const uint8_t * payload, size_t length = 0);
 | 
			
		||||
        void broadcastTXT(char * payload, size_t length = 0, bool headerToPayload = false);
 | 
			
		||||
        void broadcastTXT(const char * payload, size_t length = 0);
 | 
			
		||||
        void broadcastTXT(String payload);
 | 
			
		||||
 | 
			
		||||
        void sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload = false);
 | 
			
		||||
        void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
 | 
			
		||||
        
 | 
			
		||||
        bool sendPing(uint8_t num, uint8_t * payload = NULL, size_t length = 0);
 | 
			
		||||
        bool sendPing(uint8_t num, String & payload);
 | 
			
		||||
        
 | 
			
		||||
        bool broadcastPing(uint8_t * payload = NULL, size_t length = 0);
 | 
			
		||||
        bool broadcastPing(String & payload);
 | 
			
		||||
 | 
			
		||||
        void broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload = false);
 | 
			
		||||
        void broadcastBIN(const uint8_t * payload, size_t length);
 | 
			
		||||
 | 
			
		||||
        void disconnect(void);
 | 
			
		||||
        void disconnect(uint8_t num);
 | 
			
		||||
        
 | 
			
		||||
        bool clientConnected(uint8_t num);
 | 
			
		||||
 | 
			
		||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
 | 
			
		||||
        IPAddress remoteIP(uint8_t num);
 | 
			
		||||
#else
 | 
			
		||||
		bool clientExists(const WEBSOCKETS_NETWORK_CLASS &c);
 | 
			
		||||
        
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
        uint16_t _port;
 | 
			
		||||
 | 
			
		||||
        WEBSOCKETS_NETWORK_SERVER_CLASS * _server;
 | 
			
		||||
 | 
			
		||||
        WSclient_t _clients[WEBSOCKETS_SERVER_CLIENT_MAX];
 | 
			
		||||
 | 
			
		||||
        WebSocketServerEvent _cbEvent;
 | 
			
		||||
 | 
			
		||||
        void messageRecived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
 | 
			
		||||
 | 
			
		||||
        void clientDisconnect(WSclient_t * client);
 | 
			
		||||
        bool clientIsConnected(WSclient_t * client);
 | 
			
		||||
 | 
			
		||||
        void handleNewClients(void);
 | 
			
		||||
        void handleClientData(void);
 | 
			
		||||
 | 
			
		||||
        void handleHeader(WSclient_t * client);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * called if a non Websocket connection is comming in.
 | 
			
		||||
         * Note: can be overrided
 | 
			
		||||
         * @param client WSclient_t *  ptr to the client struct
 | 
			
		||||
         */
 | 
			
		||||
        virtual void handleNonWebsocketConnection(WSclient_t * client) {
 | 
			
		||||
            DEBUG_WEBSOCKETS("[WS-Server][");
 | 
			
		||||
            DEBUG_WEBSOCKETS(client->num);
 | 
			
		||||
            DEBUG_WEBSOCKETS("][handleHeader] no Websocket connection close.\n");
 | 
			
		||||
            
 | 
			
		||||
            client->tcp->write("HTTP/1.1 400 Bad Request\r\n"
 | 
			
		||||
                    "Server: arduino-WebSocket-Server\r\n"
 | 
			
		||||
                    "Content-Type: text/plain\r\n"
 | 
			
		||||
                    "Content-Length: 32\r\n"
 | 
			
		||||
                    "Connection: close\r\n"
 | 
			
		||||
                    "Sec-WebSocket-Version: 13\r\n"
 | 
			
		||||
                    "\r\n"
 | 
			
		||||
                    "This is a Websocket server only!");
 | 
			
		||||
            clientDisconnect(client);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * called for sending a Event to the app
 | 
			
		||||
         * @param num uint8_t
 | 
			
		||||
         * @param type WStype_t
 | 
			
		||||
         * @param payload uint8_t *
 | 
			
		||||
         * @param length size_t
 | 
			
		||||
         */
 | 
			
		||||
        virtual void runCbEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
 | 
			
		||||
            if(_cbEvent) {
 | 
			
		||||
                _cbEvent(num, type, payload, length);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* WEBSOCKETSSERVER_H_ */
 | 
			
		||||
		Reference in New Issue
	
	Block a user