Ethernet Interfaceを使用したWebSocketサーバー
Dependencies: EthernetInterface TextLCD mbed-rtos mbed
Diff: main.cpp
- Revision:
- 0:98ff551a3a1a
diff -r 000000000000 -r 98ff551a3a1a main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sat Mar 30 02:02:51 2013 +0000 @@ -0,0 +1,158 @@ +#include <string> +#include <sstream> +#include "mbed.h" +#include "EthernetInterface.h" +#include "TextLCD.h" +#include "sha1config.h" +#include "sha1.h" + +const int WS_HANDSHAKE = 1; +const int WS_CONNECT = 2; +int wsState = 0; + +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); +TextLCD lcd(p24, p26, p27, p28, p29, p30); + +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; +} + +int main() { + EthernetInterface eth; + eth.init("192.168.0.2", "255.255.255.0", "192.168.0.2"); + eth.connect(); + lcd.cls(); + lcd.printf("%s", eth.getIPAddress()); + + TCPSocketServer server; + server.bind(8080); + server.listen(); + printf("\nWait for new connection...\n"); + TCPSocketConnection sock; + server.accept(sock); + wsState = WS_HANDSHAKE; + char buff[600]; + int len; + while (true) { + len = sock.receive(buff, sizeof(buff)-1); + if (len <= 0){ + printf("close by 0 length\n"); + wsState = WS_HANDSHAKE; + continue; + } + buff[len] = '\0'; + switch(wsState){ + case WS_HANDSHAKE: + printf("Received %d chars from server:\n%s\n", len, 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", hsRes.c_str()); + sock.send_all((char *)hsRes.c_str(), hsRes.size()); + printf("change to WS_CONNECT state\n"); + wsState = WS_CONNECT; + break; + } + } + } + } + break; + case WS_CONNECT: + bool fin = (buff[0] & 0x80) == 0x80; + int opcode = buff[0] & 0x0f; + if (opcode == 0x8) { + printf("close by close opcode\n"); + wsState = WS_HANDSHAKE; + sock.close(); + break; + } + if (opcode == 0x9) { + buff[0] += 1; + sock.send_all(buff, len); + break; + } + int dataLen = buff[1] & 0x7f; + if (!fin || dataLen > 125) { + sock.close(); + printf("close by illegal data length \n"); + wsState = WS_HANDSHAKE; + break; + } + 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; + sock.send_all(sendData, 2 + dataLen); + } else if (opcode == 2) { + led1 = buff[6 + 0]; + led2 = buff[6 + 1]; + led3 = buff[6 + 2]; + led4 = buff[6 + 3]; + } + break; + } + } + + sock.close(); + eth.disconnect(); + while(1) {} +} +