Ethernet Interfaceを使用したWebSocketサーバー

Dependencies:   EthernetInterface TextLCD mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include <string>
00002 #include <sstream>
00003 #include "mbed.h"
00004 #include "EthernetInterface.h"
00005 #include "TextLCD.h"
00006 #include "sha1config.h"
00007 #include "sha1.h"
00008 
00009 const int WS_HANDSHAKE = 1;
00010 const int WS_CONNECT = 2;
00011 int wsState = 0;
00012 
00013 DigitalOut led1(LED1);
00014 DigitalOut led2(LED2);
00015 DigitalOut led3(LED3);
00016 DigitalOut led4(LED4);
00017 TextLCD lcd(p24, p26, p27, p28, p29, p30);
00018 
00019 string encode64(char *Buf,int Length) {
00020     char *Codes64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00021     int Byte3=0;
00022     string Result="";
00023     for (int i=0; i<Length; i++) {
00024         Byte3=(Byte3<<8)+(int)Buf[i];
00025         if ((i+1)%3==0) {
00026             Result=Result+Codes64[(Byte3>>18)&0x3F];
00027             Result=Result+Codes64[(Byte3>>12)&0x3F];
00028             Result=Result+Codes64[(Byte3>>6)&0x3F];
00029             Result=Result+Codes64[(Byte3)&0x3F];
00030             Byte3=0;
00031         }
00032     }
00033 
00034     int Rest=Length%3;
00035     switch (Rest) {
00036         case 1:
00037             Byte3=Byte3<<4;
00038             Result=Result+Codes64[(Byte3>>6)&0x3F];
00039             Result=Result+Codes64[(Byte3)&0x3F];
00040             Result=Result+"==";
00041             break;
00042         case 2:
00043             Byte3=Byte3<<2;
00044             Result=Result+Codes64[(Byte3>>12)&0x3F];
00045             Result=Result+Codes64[(Byte3>>6 )&0x3F];
00046             Result=Result+Codes64[(Byte3)&0x3F];
00047             Result=Result+"=";
00048             break;
00049     }
00050     return Result;
00051 }
00052 
00053 int main() {
00054     EthernetInterface eth;
00055     eth.init("192.168.0.2", "255.255.255.0", "192.168.0.2");
00056     eth.connect();
00057     lcd.cls();
00058     lcd.printf("%s", eth.getIPAddress());
00059     
00060     TCPSocketServer server;
00061     server.bind(8080);
00062     server.listen();
00063     printf("\nWait for new connection...\n");
00064     TCPSocketConnection sock;
00065     server.accept(sock);
00066     wsState = WS_HANDSHAKE;
00067     char buff[600];
00068     int len;
00069     while (true) {
00070         len = sock.receive(buff, sizeof(buff)-1);
00071         if (len <= 0){
00072             printf("close by 0 length\n");
00073             wsState = WS_HANDSHAKE;
00074             continue;
00075         }
00076         buff[len] = '\0';
00077         switch(wsState){
00078             case WS_HANDSHAKE:
00079                 printf("Received %d chars from server:\n%s\n", len, buff);
00080                 for (int i = 0; i < len; i++) {
00081                     if (buff[i] == 'K' && buff[i + 1] == 'e' && buff[i + 2] == 'y') {
00082                         for (int j = i + 1; j < len; j++) {
00083                             if (buff[j] == '\r') {
00084                                 i += 5;
00085                                 int keyLen = j - i;
00086                                 char strKey[keyLen + 1];
00087                                 strKey[keyLen] = 0;
00088                                 strncpy(strKey, buff + i, keyLen);
00089                                 char guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
00090                                 strcat(strKey, guid);
00091                                 unsigned char hash[20];
00092                                 sha1((unsigned char*)strKey,strlen((char*)strKey),hash);
00093                                 string accept = encode64((char*)hash, 20);
00094                                 string hsRes = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ";
00095                                 hsRes += accept;
00096                                 hsRes += "\r\n\r\n";
00097                                 printf("%s", hsRes.c_str());
00098                                 sock.send_all((char *)hsRes.c_str(), hsRes.size());
00099                                 printf("change to WS_CONNECT state\n");
00100                                 wsState = WS_CONNECT;
00101                                 break;
00102                             }
00103                         }
00104                     }
00105                 }
00106                 break;
00107             case WS_CONNECT:
00108                 bool fin = (buff[0] & 0x80) == 0x80;
00109                 int opcode = buff[0] & 0x0f;
00110                 if (opcode == 0x8) {
00111                     printf("close by close opcode\n");
00112                     wsState = WS_HANDSHAKE;
00113                     sock.close();
00114                     break;
00115                 }
00116                 if (opcode == 0x9) {
00117                     buff[0] += 1;
00118                     sock.send_all(buff, len);
00119                     break;
00120                 }
00121                 int dataLen = buff[1] & 0x7f;
00122                 if (!fin || dataLen > 125) {
00123                     sock.close();
00124                     printf("close by illegal data length \n");
00125                     wsState = WS_HANDSHAKE;
00126                     break;
00127                 }
00128                 int i = 0;
00129                 for (i = 0; i < dataLen; i++) {
00130                     buff[6 + i] = buff[6 + i] ^ buff[2 + (i % 4)];
00131                 }
00132                 printf("data length:%d\n", dataLen);
00133                 buff[6 + dataLen] = 0;
00134                 if (opcode == 1) {
00135                     printf("received data:%s\n", buff + 6);
00136                     char sendData[2 + dataLen + 1];
00137                     sendData[0] = buff[0];
00138                     sendData[1] = buff[1] & 0x7f;
00139                     for (i = 0; i < dataLen; i++) {
00140                         sendData[2 + i] = buff[6 + i];
00141                     }
00142                     sendData[2 + dataLen] = 0;
00143                     sock.send_all(sendData, 2 + dataLen);
00144                 } else if (opcode == 2) {
00145                     led1 = buff[6 + 0];
00146                     led2 = buff[6 + 1];
00147                     led3 = buff[6 + 2];
00148                     led4 = buff[6 + 3];
00149                 }
00150                 break;
00151         }
00152     }
00153       
00154     sock.close();
00155     eth.disconnect();
00156     while(1) {}
00157 }
00158