A Secure WebSocket client example that shows how to use the WebSocket library in SharkSSL-Lite

Dependencies:   EthernetInterface SharkSSL-Lite mbed-rtos mbed

The example connects to an online echo service and requires that you connect a terminal via the ''mbed Serial Port'. Windows users must install the Windows serial port driver.

The following screenshot shows Putty connected to the mbed serial terminal and after entering a few lines of text.

/media/uploads/wini/websocket-example.png

Files at this revision

API Documentation at this revision

Comitter:
wini
Date:
Wed Apr 06 16:43:26 2016 +0000
Commit message:
First release

Changed in this revision

EthernetInterface.lib Show annotated file Show diff for this revision Revisions of this file
SharkSSL-Lite.lib Show annotated file Show diff for this revision Revisions of this file
WsEchoClient.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 3a00a9689a7e EthernetInterface.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetInterface.lib	Wed Apr 06 16:43:26 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/EthernetInterface/#4d7bff17a592
diff -r 000000000000 -r 3a00a9689a7e SharkSSL-Lite.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SharkSSL-Lite.lib	Wed Apr 06 16:43:26 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/wini/code/SharkSSL-Lite/#e0adec41ad6b
diff -r 000000000000 -r 3a00a9689a7e WsEchoClient.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WsEchoClient.cpp	Wed Apr 06 16:43:26 2016 +0000
@@ -0,0 +1,264 @@
+/**
+ *     ____             _________                __                _
+ *    / __ \___  ____ _/ /_  __(_)___ ___  ___  / /   ____  ____ _(_)____
+ *   / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ /   / __ \/ __ `/ / ___/
+ *  / _, _/  __/ /_/ / / / / / / / / / / /  __/ /___/ /_/ / /_/ / / /__
+ * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/
+ *                                                       /____/
+ *
+ *                 SharkSSL Embedded SSL/TLS Stack
+ ****************************************************************************
+ *   PROGRAM MODULE
+ *
+ *   $Id: WsEchoClient.c 3616 2014-12-03 00:40:53Z wini $
+ *
+ *   COPYRIGHT:  Real Time Logic LLC, 2016
+ *
+ *   This software is copyrighted by and is the sole property of Real
+ *   Time Logic LLC.  All rights, title, ownership, or other interests in
+ *   the software remain the property of Real Time Logic LLC.  This
+ *   software may only be used in accordance with the terms and
+ *   conditions stipulated in the corresponding license agreement under
+ *   which the software has been supplied.  Any unauthorized use,
+ *   duplication, transmission, distribution, or disclosure of this
+ *   software is expressly forbidden.
+ *
+ *   This Copyright notice may not be removed or modified without prior
+ *   written consent of Real Time Logic LLC.
+ *
+ *   Real Time Logic LLC. reserves the right to modify this software
+ *   without notice.
+ *
+ *               http://sharkssl.com
+ ****************************************************************************
+
+
+Secure WebSocket Example
+
+WebSocket (WS) is a new standard enabling full duplex asynchronous
+communication between a web server and a client and vice versa. WS can
+be used as a base for M2M communication. See the following page for an
+introduction to the protocol: http://en.wikipedia.org/wiki/WebSocket
+
+The example is by default connecting to the WebSocket echo service at
+realtimelogic.info. Compiling the code with ECHO_EX makes the example
+connect to echo.websocket.org.
+
+The WebSocket service at realtimelogic.info can respond to both RSA
+and ECC clients, but the echo service echo.websocket.org will only
+respond with an RSA certificate. For this reason, connecting to
+echo.websocket.org will fail if you have compiled SharkSSL with the
+option to exclude RSA and to only include support for ECC.
+
+*/
+
+#include "WsClientLib.h"
+#include <mbed.h>
+#include <stdarg.h>
+
+/* 
+    The #WSHOST and #WSURI macros must point to your WebSocket server.
+*/
+#ifdef ECHO_EX
+#define WSHOST "echo.websocket.org"
+#define WSURI "/"
+#else
+#define WSHOST "realtimelogic.info"
+#define WSURI "/WS-ELIZA/"
+#endif
+
+
+/************************* Helper functions ******************************/
+
+Serial pc(USBTX, USBRX); // tx, rx
+
+/* Example code and selib.c use function xprintf.
+ */
+void _xprintf(const char* fmt, ...)
+{
+   va_list varg;
+   va_start(varg, fmt);
+   vprintf(fmt, varg);
+   va_end(varg);
+} 
+
+
+/**************************************************************************
+The following code is designed specifically for this example and
+enables non blocking read from the console. The example's main loop is
+single threaded and we most therefore use non blocking functions for
+reading from the console.
+***************************************************************************/
+
+
+/* Function pollkb requires non blocking keyboard I/O.
+ */
+
+/* Platform specific function for non blocking keyboard read.
+ */
+static int
+pollkb(void)
+{
+   if(pc.readable())
+   {
+      int c = pc.getc();
+      return c=='\r' ? '\n' : c;
+   }
+   return 0;
+}
+
+
+
+/************ End non blocking console functions ***********************/
+
+
+
+/*
+  The main function connects to a WS echo server, by using the generic
+  WS functions defined above.
+
+  The function connects to the server defined by the macro #WSHOST. See
+  WsClientLib.h for details.
+*/
+void
+mainTask(SeCtx* ctx)
+{
+   /* Info printed to the console when the program starts
+    */
+   static const char info[] = {
+      "SharkSSL Websocket client demo.\n"
+      "Copyright (c) 2016 Real Time Logic.  All rights reserved.\n"
+      "Connecting to wss://" WSHOST
+   };
+
+   SharkSsl sharkSsl;
+   SharkSslCon* sharkSslCon;
+   SOCKET sock;
+   int rc,status;
+
+   WscReadState wss={0};
+
+   xprintf(("%s",info));
+   xprintf(("y\n\n"));
+   xprintf(("Connecting to " WSHOST "...\n"));
+   /* Port 443 is the listen port for secure servers i.e. HTTPS */
+   status=se_connect(&sock, WSHOST, 443);
+   if(status)
+   {
+      const char* msg;
+      switch(status)
+      {
+         case -1: msg="Socket error!";
+            break;
+         case -2: msg="Cannot resolve IP address for " WSHOST ".";
+            break;
+         default:  msg="Cannot connect to " WSHOST ".";
+      }
+      xprintf((
+         "%s\n%s",
+         msg,
+         status == -1 ? "" :
+         "Note: this example is not designed to connect via a HTTP proxy.\n"));
+      return;
+   }
+
+   /* It is common to create one (or several) SharkSsl object(s) at
+      system start and to keep these objects for the lifetime of the
+      program/firmware.
+    */
+   SharkSsl_constructor(&sharkSsl,
+                        SharkSsl_Client, /* Two options: client or server */
+                        0,      /* Not using SSL cache */
+                        4000,   /* initial inBuf size: Can grow */
+                        4000);   /* outBuf size: Fixed */
+   
+   /* It is very important to seed the SharkSSL RNG generator (Ref-seed) */
+   sharkssl_entropy(baGetUnixTime() ^ (U32)&sharkSsl);
+
+   if( (sharkSslCon = SharkSsl_createCon(&sharkSsl)) == 0)
+      xprintf(("Cannot create SharkSslCon object.\n"));
+   else /* We are now connected to the server. */
+   {
+      /* Keep seeding (Make it more secure: Ref-seed) */
+      sharkssl_entropy(baGetUnixTime() ^ (U32)&sharkSsl);
+      /* Establish a WS connection */
+      if( ! wscProtocolHandshake(&wss, sharkSslCon, &sock,6000,WSHOST,WSURI,0))
+      {
+         U8 sbuf[255];
+         int sbufIx=0; /* sbuf cursor */
+         U8* rbuf; /* Receive buffer is managed by SharkSSL */
+         int idleCounter=0;
+#ifdef ECHO_EX
+         xprintf(("\n------\nConnected\nEnter data and press the ENTER key\n"));
+#endif
+         while((rc = wscRead(&wss,sharkSslCon,&sock,&rbuf,50)) >= 0)
+         {
+            if(rc) /* incomming data from server */
+            {
+               idleCounter=0;
+#ifdef ECHO_EX
+               xprintf(("Received %d bytes from server:\n",wss.frameLen));
+#endif
+               do
+               {
+                  int len=rc;
+                  while(len--)
+                     xprintf(("%c", *rbuf++));
+                  if(wss.bytesRead == wss.frameLen)
+                     break; /* We are done receiving the current frame */
+               } while( (rc=wscRead(&wss,sharkSslCon,&sock,&rbuf,10000)) > 0 );
+#ifdef ECHO_EX
+               xprintf(("\nEnd WS frame.\n"));
+#endif
+               if(rc <= 0) break;
+            }
+            else /* 50 ms timeout */
+            {
+               int c;
+               /* Check if we have console data i.e. if user
+                * entered text into the console. */
+               while((c=pollkb())!=0)
+               {
+                  xprintf(("%c",c));
+                  sbuf[sbufIx++] = (U8)c;
+                  /* Flush on ENTER or if buffer is full */
+                  if(c == '\n' || sbufIx == sizeof(sbuf))
+                  {
+                     /* Send console data to server */
+                     rc = wscSendBin(sharkSslCon,&sock,sbuf,sbufIx);
+                     sbufIx=0;
+                     idleCounter=0;
+                     if(c != '\n')
+                        xprintf(("\n"));
+                     break;
+                  }
+               }
+               if(rc < 0) break;
+            }
+            if(rc == 0)
+            {
+               if(++idleCounter == 100) /* 50ms * 100: 5 sec */
+               {
+                  static const U8 msg[]={"Are you still there?"};
+                  idleCounter=0;
+                  /* There are no WS requirements for sending
+                   * pings. This is just an example. (Ref-Ping). Note,
+                   * ping payload data is not required.
+                   */
+                  rc=wscSendCtrl(
+                     sharkSslCon,&sock,WSOP_Ping,msg,sizeof(msg)-1);
+                  if(rc < 0) break;
+               }
+            }
+         }
+      }
+      /* Release resources used by sharkSslCon */
+      SharkSsl_terminateCon(&sharkSsl, sharkSslCon);
+   }
+
+   SharkSsl_destructor(&sharkSsl);
+   se_close(&sock);
+   /*! [inline doc] */
+   xprintf(("\nServer connection closed!"));
+}
+
diff -r 000000000000 -r 3a00a9689a7e main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Apr 06 16:43:26 2016 +0000
@@ -0,0 +1,13 @@
+#include "mbed.h"
+#include "EthernetInterface.h"
+#include <selib.h>
+
+int main() {
+    EthernetInterface eth;
+    eth.init(); //Use DHCP
+    eth.connect();
+    printf("IP Address is %s\n", eth.getIPAddress());
+   mainTask(0);
+   error("mainTask returned");
+}
+
diff -r 000000000000 -r 3a00a9689a7e mbed-rtos.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Wed Apr 06 16:43:26 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#bdd541595fc5
diff -r 000000000000 -r 3a00a9689a7e mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Apr 06 16:43:26 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/99a22ba036c9
\ No newline at end of file