Skip to content

Commit

Permalink
Add websocket example that supports permessage-deflate extension
Browse files Browse the repository at this point in the history
  • Loading branch information
luisbebop committed Jun 4, 2016
1 parent 71f4609 commit 145479f
Show file tree
Hide file tree
Showing 19 changed files with 2,175 additions and 1 deletion.
4 changes: 4 additions & 0 deletions examples/websocket_mbedtls/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PROGRAM=websocket_mbedtls
COMPONENTS = FreeRTOS lwip core extras/mbedtls

include ../../common.mk
78 changes: 78 additions & 0 deletions examples/websocket_mbedtls/adler32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Adler-32 checksum
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/

/*
* Adler-32 algorithm taken from the zlib source, which is
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
*/

#include "tinf.h"

#define A32_BASE 65521
#define A32_NMAX 5552

unsigned int tinf_adler32(const void *data, unsigned int length)
{
const unsigned char *buf = (const unsigned char *)data;

unsigned int s1 = 1;
unsigned int s2 = 0;

while (length > 0)
{
int k = length < A32_NMAX ? length : A32_NMAX;
int i;

for (i = k / 16; i; --i, buf += 16)
{
s1 += buf[0]; s2 += s1; s1 += buf[1]; s2 += s1;
s1 += buf[2]; s2 += s1; s1 += buf[3]; s2 += s1;
s1 += buf[4]; s2 += s1; s1 += buf[5]; s2 += s1;
s1 += buf[6]; s2 += s1; s1 += buf[7]; s2 += s1;

s1 += buf[8]; s2 += s1; s1 += buf[9]; s2 += s1;
s1 += buf[10]; s2 += s1; s1 += buf[11]; s2 += s1;
s1 += buf[12]; s2 += s1; s1 += buf[13]; s2 += s1;
s1 += buf[14]; s2 += s1; s1 += buf[15]; s2 += s1;
}

for (i = k % 16; i; --i) { s1 += *buf++; s2 += s1; }

s1 %= A32_BASE;
s2 %= A32_BASE;

length -= k;
}

return (s2 << 16) | s1;
}
44 changes: 44 additions & 0 deletions examples/websocket_mbedtls/cert.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* This is the CA certificate for the CA trust chain of
www.howsmyssl.com in PEM format, as dumped via:
openssl s_client -showcerts -connect www.howsmyssl.com:443 </dev/null
The CA cert is the last cert in the chain output by the server.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>

/*
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
*/
const char *server_root_cert = "-----BEGIN CERTIFICATE-----\r\n"
"MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\r\n"
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\r\n"
"DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\r\n"
"SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\r\n"
"GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\r\n"
"AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\r\n"
"q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\r\n"
"SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\r\n"
"Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\r\n"
"a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\r\n"
"/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\r\n"
"AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\r\n"
"CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\r\n"
"bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\r\n"
"c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\r\n"
"VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\r\n"
"ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\r\n"
"MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\r\n"
"Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\r\n"
"AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\r\n"
"uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\r\n"
"wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\r\n"
"X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\r\n"
"PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\r\n"
"KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\r\n"
"-----END CERTIFICATE-----\r\n";


229 changes: 229 additions & 0 deletions examples/websocket_mbedtls/conn.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#include "espressif/esp_common.h"
#include "esp/uart.h"

#include <string.h>

#include "FreeRTOS.h"
#include "task.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "lwip/api.h"

#include "ssid_config.h"

/* mbedtls/config.h MUST appear before all other mbedtls headers, or
you'll get the default config.
(Although mostly that isn't a big problem, you just might get
errors at link time if functions don't exist.) */
#include "mbedtls/config.h"

#include "mbedtls/net.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/certs.h"

#include <stdio.h>
#include <string.h>

#include "conn.h"

/* SSL file descriptors */
#define SSL_HANDLES_SIZE 4
mbedtls_ssl_context* sslHandles[SSL_HANDLES_SIZE] = {NULL, NULL, NULL, NULL};
unsigned char ctxC = 0;

mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;

/* Connect to a hostname and port using TLS 1.2 and
return a index for one SSL connection on the pool or -1 if error
*/
int ConnConnect(char *hostname, int port) {
int ret = 0;
mbedtls_ssl_context *sslFD;
mbedtls_net_context *socketFD;
int sslHandle = 0;
char s_port[10];

// configure mbedtls
if (!ctxC) {
mbedtls_ssl_config_init( &conf );
mbedtls_x509_crt_init( &cacert );
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_entropy_init( &entropy );

if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) "ssl_client1",
strlen( "ssl_client1" ) ) ) != 0 )
{
printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
return -1;
}

ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
mbedtls_test_cas_pem_len );
if( ret < 0 )
{
printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
return -1;
}


if( ( ret = mbedtls_ssl_config_defaults( &conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
{
printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
return -1;
}

mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );

ctxC = 1;
}

// find a free slot at sslHandles
while(sslHandle < SSL_HANDLES_SIZE) {
if (sslHandles[sslHandle] == NULL) {
sslFD = malloc(sizeof(mbedtls_ssl_context));
socketFD = malloc(sizeof(mbedtls_net_context));
mbedtls_ssl_init( sslFD );
mbedtls_net_init( socketFD );
sslHandles[sslHandle] = sslFD;
break;
}
sslHandle++;
}

// no free slot at sslHandles
if (sslHandle == SSL_HANDLES_SIZE) {
return -1;
}

// connect mbedtls socket
memset(s_port, 0, sizeof(s_port));
sprintf(s_port, "%d", port);
ret = mbedtls_net_connect(socketFD, hostname, s_port, MBEDTLS_NET_PROTO_TCP);
if (ret != 0) {
ConnClose(sslHandle);
return -1;
}

if(( ret = mbedtls_ssl_setup( sslFD, &conf ) ) != 0 )
{
printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret );
ConnClose(sslHandle);
return -1;
}

if( ( ret = mbedtls_ssl_set_hostname( sslFD, "mbed TLS Server 1" ) ) != 0 )
{
printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
ConnClose(sslHandle);
return -1;
}

mbedtls_ssl_set_bio( sslFD, socketFD, mbedtls_net_send, mbedtls_net_recv, NULL );

while( ( ret = mbedtls_ssl_handshake( sslFD ) ) != 0 )
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
ConnClose(sslHandle);
return -1;
}
}

return sslHandle;
}

int ConnReadBytesAvailable(int sslHandle) {
mbedtls_ssl_context* sslFD = NULL;
mbedtls_net_context* socketFD = NULL;
int count = 0;

if (sslHandle >= 0) sslFD = sslHandles[sslHandle];
else return -1;

if (sslFD) {
socketFD = (mbedtls_net_context *) sslFD->p_bio;
lwip_ioctl(socketFD->fd, FIONREAD, &count);
return count;
} else {
return -1;
}
}

/* Read bytes from a valid SSL connection on the pool. Blocking! */
int ConnRead(int sslHandle, void *buf, int num) {
mbedtls_ssl_context* sslFD = NULL;
int ret;

if (sslHandle >= 0) sslFD = sslHandles[sslHandle];
else return -1;

if (sslFD) {
if (num == 0) return 0;
ret = mbedtls_ssl_read(sslFD, buf, num);
return ret;
} else {
return -1;
}
}

/* Write bytes to a valid SSL connection on the pool */
int ConnWrite(int sslHandle, const void *buf, int num) {
mbedtls_ssl_context* sslFD = NULL;
int ret;

if (sslHandle >= 0) sslFD = sslHandles[sslHandle];
else return -1;

if (sslFD) {
if (num == 0) return 0;
ret = mbedtls_ssl_write(sslFD, buf, num);
return ret;
} else {
return -1;
}
}

/* Close a valid SSL connection on the pool, release the resources and
open the slot to another connection */
void ConnClose(int sslHandle) {
mbedtls_ssl_context *sslFD = NULL;

if (sslHandle >= 0) sslFD = sslHandles[sslHandle];
else return;

if (sslFD) {
mbedtls_ssl_close_notify( sslFD );

mbedtls_net_free( sslFD->p_bio );
free(sslFD->p_bio);

mbedtls_ssl_free( sslFD );
free(sslFD);
}

sslHandles[sslHandle] = NULL;
}

void sleep_ms(int milliseconds)
{
vTaskDelay(milliseconds / portTICK_RATE_MS);
}
11 changes: 11 additions & 0 deletions examples/websocket_mbedtls/conn.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef CONN
#define CONN

int ConnConnect(char *host, int port);
int ConnReadBytesAvailable(int sslHandle);
int ConnRead(int sslHandle, void *buf, int num);
int ConnWrite(int sslHandle, const void *buf, int num);
void ConnClose(int sslHandle);
void sleep_ms(int milliseconds);

#endif
Loading

0 comments on commit 145479f

Please sign in to comment.