WebSocketServer test

Dependencies:   mbed

Revision:
0:74be48b504a5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Apr 29 03:58:08 2012 +0000
@@ -0,0 +1,333 @@
+#include <string>
+#include <sstream>
+#include "mbed.h"
+#include "TextLCD.h"
+#include "EthernetNetIf.h"
+#include "TCPSocket.h"
+#include "sha1config.h"
+#include "sha1.h"
+
+//EthernetNetIf eth;
+EthernetNetIf  eth(
+    IpAddr(192,168,0,2), //IP Address
+    IpAddr(255,255,255,0), //Network Mask
+    IpAddr(192,168,0,1), //Gateway
+    IpAddr(192,168,0,1)  //DNS
+);
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+TCPSocket tcp;  //The listening port where requests are queued
+TCPSocket* link; //The port where accepted requests can communicate
+IpAddr localIp = IpAddr(192, 168, 0, 2);
+int localPort = 80;
+Host local(localIp, localPort); //mbed IP
+Host client;
+
+TextLCD lcd(p24, p26, p27, p28, p29, p30);
+
+TCPSocketErr accErr;
+int wsState = 0;
+
+// encode64 from http://uinu.org/archives/105
+string encode64(char *Buf,int Length) {
+    char *Codes64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    int Byte3=0;
+    string Result="";
+    for (int i=0; i<Length; i++) {
+        Byte3=(Byte3<<8)+(int)Buf[i];
+        if ((i+1)%3==0) {
+            Result=Result+Codes64[(Byte3>>18)&0x3F];
+            Result=Result+Codes64[(Byte3>>12)&0x3F];
+            Result=Result+Codes64[(Byte3>>6)&0x3F];
+            Result=Result+Codes64[(Byte3)&0x3F];
+            Byte3=0;
+        }
+    }
+
+    int Rest=Length%3;
+    switch (Rest) {
+        case 1:
+            Byte3=Byte3<<4;
+            Result=Result+Codes64[(Byte3>>6)&0x3F];
+            Result=Result+Codes64[(Byte3)&0x3F];
+            Result=Result+"==";
+            break;
+        case 2:
+            Byte3=Byte3<<2;
+            Result=Result+Codes64[(Byte3>>12)&0x3F];
+            Result=Result+Codes64[(Byte3>>6 )&0x3F];
+            Result=Result+Codes64[(Byte3)&0x3F];
+            Result=Result+"=";
+            break;
+    }
+    return Result;
+}
+
+void onLinkSocketEvent(TCPSocketEvent e) {
+    switch (e) {
+        case TCPSOCKET_CONNECTED:
+            printf("TCP Socket Connected\n");
+            break;
+        case TCPSOCKET_WRITEABLE:
+            //Can now write some data...
+            printf("TCP Socket Writable\n");
+            break;
+        case TCPSOCKET_READABLE:
+            //Can now read dome data...
+            printf("TCP Socket Readable\n");
+            // Read in any available data into the buffer
+            char buff[256];
+            while ( int len = link->recv(buff, 256) ) {
+                // And send straight back out again
+                //link->send(buff, len);
+                printf("len = %d\n", len);
+                if (wsState == 0) {
+                    buff[len]=0; // make terminater
+                    printf("%s\n", (char*)buff);
+                    for (int i = 0; i < len; i++) {
+                        if (buff[i] == 'K' && buff[i + 1] == 'e' && buff[i + 2] == 'y') {
+                            for (int j = i + 1; j < len; j++) {
+                                if (buff[j] == '\r') {
+                                    i += 5;
+                                    int keyLen = j - i;
+                                    char strKey[keyLen + 1];
+                                    strKey[keyLen] = 0;
+                                    strncpy(strKey, buff + i, keyLen);
+                                    char guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+                                    strcat(strKey, guid);
+                                    unsigned char hash[20];
+                                    sha1((unsigned char*)strKey,strlen((char*)strKey),hash);
+                                    string accept = encode64((char*)hash, 20);
+                                    string hsRes = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ";
+                                    hsRes += accept;
+                                    hsRes += "\r\n\r\n";
+                                    printf("%s\n", hsRes.c_str());
+                                    link->send(hsRes.c_str(), hsRes.size());
+                                    wsState = 1;
+                                    return;
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    if (len == 0) {
+                        link->close();
+                        return;
+                    }
+                    bool fin = (buff[0] & 0x80) == 0x80;
+                    int opcode = buff[0] & 0x0f;
+                    if (opcode == 0x9) {
+                        buff[0] += 1;
+                        link->send(buff, len);
+                        return;
+                    }
+                    int dataLen = buff[1] & 0x7f;
+                    if (!fin || dataLen > 125) {
+                        link->close();
+                        return;
+                    }
+                    int i = 0;
+                    for (i = 0; i < dataLen; i++) {
+                        buff[6 + i] = buff[6 + i] ^ buff[2 + (i % 4)];
+                    }
+                    printf("data length:%d\n", dataLen);
+                    buff[6 + dataLen] = 0;
+                    if (opcode == 1) {
+                        printf("received data:%s\n", buff + 6);
+                        char sendData[2 + dataLen + 1];
+                        sendData[0] = buff[0];
+                        sendData[1] = buff[1] & 0x7f;
+                        for (i = 0; i < dataLen; i++) {
+                            sendData[2 + i] = buff[6 + i];
+                        }
+                        sendData[2 + dataLen] = 0;
+                        link->send(sendData, 2 + dataLen);
+                    } else if (opcode == 2) {
+                        led1 = buff[6 + 0];
+                        led2 = buff[6 + 1];
+                        led3 = buff[6 + 2];
+                        led4 = buff[6 + 3];
+                    }
+                }
+            };
+            break;
+        case TCPSOCKET_CONTIMEOUT:
+            printf("TCP Socket Timeout\n");
+            break;
+        case TCPSOCKET_CONRST:
+            printf("TCP Socket CONRST\n");
+            break;
+        case TCPSOCKET_CONABRT:
+            printf("TCP Socket CONABRT\n");
+            break;
+        case TCPSOCKET_ERROR:
+            printf("TCP Socket Error\n");
+            link->close();
+            break;
+        case TCPSOCKET_DISCONNECTED:
+            printf("TCP Socket Disconnected\n");
+            wsState = 0;
+            link->close();
+            break;
+        default:
+            printf("DEFAULT\n");
+    }
+}
+
+void onTCPSocketEvent(TCPSocketEvent e) {
+    switch (e) {
+        case TCPSOCKET_CONNECTED:
+            printf("Connected\n");
+            break;
+
+        case TCPSOCKET_ACCEPT: {
+            accErr = tcp.accept(&client,&link);
+            switch (accErr) {
+                case TCPSOCKET_SETUP:
+                    printf("Err:Setup\n");
+                    break;  //TCPSocket not properly configured.
+                case TCPSOCKET_TIMEOUT:
+                    printf("Err:Timeout\n");
+                    break;  //Connection timed out.
+                case TCPSOCKET_IF:
+                    printf("Err:Interface\n");
+                    break;  //Interface has problems, does not exist or is not initialized.
+                case TCPSOCKET_MEM:
+                    printf("Err:Memory\n");
+                    break;  //Not enough mem.
+                case TCPSOCKET_INUSE:
+                    printf("Err:In use\n");
+                    break;  //Interface / Port is in use.
+                case TCPSOCKET_EMPTY:
+                    printf("Err:Empty\n");
+                    break;  //Connections queue is empty.
+                case TCPSOCKET_RST:
+                    printf("Err:Reset\n");
+                    break;  //Connection was reset by remote host.
+                case TCPSOCKET_OK:
+                    printf("Accepted: ");
+                    break;  //Success.
+            }
+            link->setOnEvent(&onLinkSocketEvent);
+            IpAddr clientIp = client.getIp();
+            printf("Incoming TCP connection from %d.%d.%d.%d\n",
+                   clientIp[0], clientIp[1], clientIp[2], clientIp[3]);
+        }
+        break;
+
+        case TCPSOCKET_READABLE:
+            printf("Readable\n");
+            break;
+
+        case TCPSOCKET_WRITEABLE:
+            printf("Writeable\n");
+            break;
+
+        case TCPSOCKET_CONTIMEOUT:
+            printf("Timeout\n");
+            break;
+
+        case TCPSOCKET_CONRST:
+            printf("Reset\n");
+            break;
+        case TCPSOCKET_CONABRT:
+            printf("Aborted\n");
+            break;
+
+        case TCPSOCKET_ERROR:
+            printf("Error\n");
+            break;
+
+        case TCPSOCKET_DISCONNECTED:
+            printf("Disconnected\n");
+            tcp.close();
+            break;
+    }
+}
+
+int main() {
+    printf("Setting up...\n");
+    EthernetErr ethErr = eth.setup();
+    if (ethErr) {
+        printf("Error %d in setup.\n", ethErr);
+        return -1;
+    }
+
+    printf("Setup OK\n");
+    //****End of basic setup*****
+
+    tcp.setOnEvent(&onTCPSocketEvent); //Generate method to deal with requests
+
+    //Bind to local port
+    printf("Init bind..\n");
+    TCPSocketErr bindErr = tcp.bind(local);
+    switch (bindErr) {
+        case TCPSOCKET_SETUP:
+            printf("Err:Setup\n");
+            return -1;  //TCPSocket not properly configured.
+        case TCPSOCKET_TIMEOUT:
+            printf("Err:Timeout\n");
+            return -1;  //Connection timed out.
+        case TCPSOCKET_IF:
+            printf("Err:Interface\n");
+            return -1;  //Interface has problems, does not exist or is not initialized.
+        case TCPSOCKET_MEM:
+            printf("Err:Memory\n");
+            return -1;  //Not enough mem.
+        case TCPSOCKET_INUSE:
+            printf("Err:In use\n");
+            return -1;  //Interface / Port is in use.
+        case TCPSOCKET_EMPTY:
+            printf("Err:Empty\n");
+            return -1;  //Connections queue is empty.
+        case TCPSOCKET_RST:
+            printf("Err:Reset\n");
+            return -1;  //Connection was reset by remote host.
+        case TCPSOCKET_OK:
+            printf("Bound to port\n");
+            break;  //Success.
+    }
+
+    //Listen to local port
+    printf("Init listen..\n");
+    TCPSocketErr listenErr = tcp.listen();
+    switch (listenErr) {
+        case TCPSOCKET_SETUP:
+            printf("Err:Setup\n");
+            return -1;  //TCPSocket not properly configured.
+        case TCPSOCKET_TIMEOUT:
+            printf("Err:Timeout\n");
+            return -1;  //Connection timed out.
+        case TCPSOCKET_IF:
+            printf("Err:Interface\n");
+            return -1;  //Interface has problems, does not exist or is not initialized.
+        case TCPSOCKET_MEM:
+            printf("Err:Memory\n");
+            return -1;  //Not enough mem.
+        case TCPSOCKET_INUSE:
+            printf("Err:In use\n");
+            return -1;  //Interface / Port is in use.
+        case TCPSOCKET_EMPTY:
+            printf("Err:Empty\n");
+            return -1;  //Connections queue is empty.
+        case TCPSOCKET_RST:
+            printf("Err:Reset\n");
+            return -1;  //Connection was reset by remote host.
+        case TCPSOCKET_OK:
+            printf("Listening\n");
+            break;  //Success.
+    }
+
+    Timer tmr;
+    tmr.start();
+    while (1) {
+        Net::poll();
+        if (tmr.read() > 2) {
+            tmr.reset();
+            //led1=!led1; //Show that we are alive
+        }
+    }
+}