Ethernet Interfaceを使用したWebSocketサーバー
Dependencies: EthernetInterface TextLCD mbed-rtos mbed
main.cpp
- Committer:
- gtk2k
- Date:
- 2013-03-30
- Revision:
- 0:98ff551a3a1a
File content as of revision 0:98ff551a3a1a:
#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) {} }