Ethernet Interfaceを使用したWebSocketサーバー
Dependencies: EthernetInterface TextLCD mbed-rtos mbed
main.cpp@0:98ff551a3a1a, 2013-03-30 (annotated)
- Committer:
- gtk2k
- Date:
- Sat Mar 30 02:02:51 2013 +0000
- Revision:
- 0:98ff551a3a1a
Ethernet Interface?????WebSocketServer
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gtk2k | 0:98ff551a3a1a | 1 | #include <string> |
gtk2k | 0:98ff551a3a1a | 2 | #include <sstream> |
gtk2k | 0:98ff551a3a1a | 3 | #include "mbed.h" |
gtk2k | 0:98ff551a3a1a | 4 | #include "EthernetInterface.h" |
gtk2k | 0:98ff551a3a1a | 5 | #include "TextLCD.h" |
gtk2k | 0:98ff551a3a1a | 6 | #include "sha1config.h" |
gtk2k | 0:98ff551a3a1a | 7 | #include "sha1.h" |
gtk2k | 0:98ff551a3a1a | 8 | |
gtk2k | 0:98ff551a3a1a | 9 | const int WS_HANDSHAKE = 1; |
gtk2k | 0:98ff551a3a1a | 10 | const int WS_CONNECT = 2; |
gtk2k | 0:98ff551a3a1a | 11 | int wsState = 0; |
gtk2k | 0:98ff551a3a1a | 12 | |
gtk2k | 0:98ff551a3a1a | 13 | DigitalOut led1(LED1); |
gtk2k | 0:98ff551a3a1a | 14 | DigitalOut led2(LED2); |
gtk2k | 0:98ff551a3a1a | 15 | DigitalOut led3(LED3); |
gtk2k | 0:98ff551a3a1a | 16 | DigitalOut led4(LED4); |
gtk2k | 0:98ff551a3a1a | 17 | TextLCD lcd(p24, p26, p27, p28, p29, p30); |
gtk2k | 0:98ff551a3a1a | 18 | |
gtk2k | 0:98ff551a3a1a | 19 | string encode64(char *Buf,int Length) { |
gtk2k | 0:98ff551a3a1a | 20 | char *Codes64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
gtk2k | 0:98ff551a3a1a | 21 | int Byte3=0; |
gtk2k | 0:98ff551a3a1a | 22 | string Result=""; |
gtk2k | 0:98ff551a3a1a | 23 | for (int i=0; i<Length; i++) { |
gtk2k | 0:98ff551a3a1a | 24 | Byte3=(Byte3<<8)+(int)Buf[i]; |
gtk2k | 0:98ff551a3a1a | 25 | if ((i+1)%3==0) { |
gtk2k | 0:98ff551a3a1a | 26 | Result=Result+Codes64[(Byte3>>18)&0x3F]; |
gtk2k | 0:98ff551a3a1a | 27 | Result=Result+Codes64[(Byte3>>12)&0x3F]; |
gtk2k | 0:98ff551a3a1a | 28 | Result=Result+Codes64[(Byte3>>6)&0x3F]; |
gtk2k | 0:98ff551a3a1a | 29 | Result=Result+Codes64[(Byte3)&0x3F]; |
gtk2k | 0:98ff551a3a1a | 30 | Byte3=0; |
gtk2k | 0:98ff551a3a1a | 31 | } |
gtk2k | 0:98ff551a3a1a | 32 | } |
gtk2k | 0:98ff551a3a1a | 33 | |
gtk2k | 0:98ff551a3a1a | 34 | int Rest=Length%3; |
gtk2k | 0:98ff551a3a1a | 35 | switch (Rest) { |
gtk2k | 0:98ff551a3a1a | 36 | case 1: |
gtk2k | 0:98ff551a3a1a | 37 | Byte3=Byte3<<4; |
gtk2k | 0:98ff551a3a1a | 38 | Result=Result+Codes64[(Byte3>>6)&0x3F]; |
gtk2k | 0:98ff551a3a1a | 39 | Result=Result+Codes64[(Byte3)&0x3F]; |
gtk2k | 0:98ff551a3a1a | 40 | Result=Result+"=="; |
gtk2k | 0:98ff551a3a1a | 41 | break; |
gtk2k | 0:98ff551a3a1a | 42 | case 2: |
gtk2k | 0:98ff551a3a1a | 43 | Byte3=Byte3<<2; |
gtk2k | 0:98ff551a3a1a | 44 | Result=Result+Codes64[(Byte3>>12)&0x3F]; |
gtk2k | 0:98ff551a3a1a | 45 | Result=Result+Codes64[(Byte3>>6 )&0x3F]; |
gtk2k | 0:98ff551a3a1a | 46 | Result=Result+Codes64[(Byte3)&0x3F]; |
gtk2k | 0:98ff551a3a1a | 47 | Result=Result+"="; |
gtk2k | 0:98ff551a3a1a | 48 | break; |
gtk2k | 0:98ff551a3a1a | 49 | } |
gtk2k | 0:98ff551a3a1a | 50 | return Result; |
gtk2k | 0:98ff551a3a1a | 51 | } |
gtk2k | 0:98ff551a3a1a | 52 | |
gtk2k | 0:98ff551a3a1a | 53 | int main() { |
gtk2k | 0:98ff551a3a1a | 54 | EthernetInterface eth; |
gtk2k | 0:98ff551a3a1a | 55 | eth.init("192.168.0.2", "255.255.255.0", "192.168.0.2"); |
gtk2k | 0:98ff551a3a1a | 56 | eth.connect(); |
gtk2k | 0:98ff551a3a1a | 57 | lcd.cls(); |
gtk2k | 0:98ff551a3a1a | 58 | lcd.printf("%s", eth.getIPAddress()); |
gtk2k | 0:98ff551a3a1a | 59 | |
gtk2k | 0:98ff551a3a1a | 60 | TCPSocketServer server; |
gtk2k | 0:98ff551a3a1a | 61 | server.bind(8080); |
gtk2k | 0:98ff551a3a1a | 62 | server.listen(); |
gtk2k | 0:98ff551a3a1a | 63 | printf("\nWait for new connection...\n"); |
gtk2k | 0:98ff551a3a1a | 64 | TCPSocketConnection sock; |
gtk2k | 0:98ff551a3a1a | 65 | server.accept(sock); |
gtk2k | 0:98ff551a3a1a | 66 | wsState = WS_HANDSHAKE; |
gtk2k | 0:98ff551a3a1a | 67 | char buff[600]; |
gtk2k | 0:98ff551a3a1a | 68 | int len; |
gtk2k | 0:98ff551a3a1a | 69 | while (true) { |
gtk2k | 0:98ff551a3a1a | 70 | len = sock.receive(buff, sizeof(buff)-1); |
gtk2k | 0:98ff551a3a1a | 71 | if (len <= 0){ |
gtk2k | 0:98ff551a3a1a | 72 | printf("close by 0 length\n"); |
gtk2k | 0:98ff551a3a1a | 73 | wsState = WS_HANDSHAKE; |
gtk2k | 0:98ff551a3a1a | 74 | continue; |
gtk2k | 0:98ff551a3a1a | 75 | } |
gtk2k | 0:98ff551a3a1a | 76 | buff[len] = '\0'; |
gtk2k | 0:98ff551a3a1a | 77 | switch(wsState){ |
gtk2k | 0:98ff551a3a1a | 78 | case WS_HANDSHAKE: |
gtk2k | 0:98ff551a3a1a | 79 | printf("Received %d chars from server:\n%s\n", len, buff); |
gtk2k | 0:98ff551a3a1a | 80 | for (int i = 0; i < len; i++) { |
gtk2k | 0:98ff551a3a1a | 81 | if (buff[i] == 'K' && buff[i + 1] == 'e' && buff[i + 2] == 'y') { |
gtk2k | 0:98ff551a3a1a | 82 | for (int j = i + 1; j < len; j++) { |
gtk2k | 0:98ff551a3a1a | 83 | if (buff[j] == '\r') { |
gtk2k | 0:98ff551a3a1a | 84 | i += 5; |
gtk2k | 0:98ff551a3a1a | 85 | int keyLen = j - i; |
gtk2k | 0:98ff551a3a1a | 86 | char strKey[keyLen + 1]; |
gtk2k | 0:98ff551a3a1a | 87 | strKey[keyLen] = 0; |
gtk2k | 0:98ff551a3a1a | 88 | strncpy(strKey, buff + i, keyLen); |
gtk2k | 0:98ff551a3a1a | 89 | char guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
gtk2k | 0:98ff551a3a1a | 90 | strcat(strKey, guid); |
gtk2k | 0:98ff551a3a1a | 91 | unsigned char hash[20]; |
gtk2k | 0:98ff551a3a1a | 92 | sha1((unsigned char*)strKey,strlen((char*)strKey),hash); |
gtk2k | 0:98ff551a3a1a | 93 | string accept = encode64((char*)hash, 20); |
gtk2k | 0:98ff551a3a1a | 94 | string hsRes = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "; |
gtk2k | 0:98ff551a3a1a | 95 | hsRes += accept; |
gtk2k | 0:98ff551a3a1a | 96 | hsRes += "\r\n\r\n"; |
gtk2k | 0:98ff551a3a1a | 97 | printf("%s", hsRes.c_str()); |
gtk2k | 0:98ff551a3a1a | 98 | sock.send_all((char *)hsRes.c_str(), hsRes.size()); |
gtk2k | 0:98ff551a3a1a | 99 | printf("change to WS_CONNECT state\n"); |
gtk2k | 0:98ff551a3a1a | 100 | wsState = WS_CONNECT; |
gtk2k | 0:98ff551a3a1a | 101 | break; |
gtk2k | 0:98ff551a3a1a | 102 | } |
gtk2k | 0:98ff551a3a1a | 103 | } |
gtk2k | 0:98ff551a3a1a | 104 | } |
gtk2k | 0:98ff551a3a1a | 105 | } |
gtk2k | 0:98ff551a3a1a | 106 | break; |
gtk2k | 0:98ff551a3a1a | 107 | case WS_CONNECT: |
gtk2k | 0:98ff551a3a1a | 108 | bool fin = (buff[0] & 0x80) == 0x80; |
gtk2k | 0:98ff551a3a1a | 109 | int opcode = buff[0] & 0x0f; |
gtk2k | 0:98ff551a3a1a | 110 | if (opcode == 0x8) { |
gtk2k | 0:98ff551a3a1a | 111 | printf("close by close opcode\n"); |
gtk2k | 0:98ff551a3a1a | 112 | wsState = WS_HANDSHAKE; |
gtk2k | 0:98ff551a3a1a | 113 | sock.close(); |
gtk2k | 0:98ff551a3a1a | 114 | break; |
gtk2k | 0:98ff551a3a1a | 115 | } |
gtk2k | 0:98ff551a3a1a | 116 | if (opcode == 0x9) { |
gtk2k | 0:98ff551a3a1a | 117 | buff[0] += 1; |
gtk2k | 0:98ff551a3a1a | 118 | sock.send_all(buff, len); |
gtk2k | 0:98ff551a3a1a | 119 | break; |
gtk2k | 0:98ff551a3a1a | 120 | } |
gtk2k | 0:98ff551a3a1a | 121 | int dataLen = buff[1] & 0x7f; |
gtk2k | 0:98ff551a3a1a | 122 | if (!fin || dataLen > 125) { |
gtk2k | 0:98ff551a3a1a | 123 | sock.close(); |
gtk2k | 0:98ff551a3a1a | 124 | printf("close by illegal data length \n"); |
gtk2k | 0:98ff551a3a1a | 125 | wsState = WS_HANDSHAKE; |
gtk2k | 0:98ff551a3a1a | 126 | break; |
gtk2k | 0:98ff551a3a1a | 127 | } |
gtk2k | 0:98ff551a3a1a | 128 | int i = 0; |
gtk2k | 0:98ff551a3a1a | 129 | for (i = 0; i < dataLen; i++) { |
gtk2k | 0:98ff551a3a1a | 130 | buff[6 + i] = buff[6 + i] ^ buff[2 + (i % 4)]; |
gtk2k | 0:98ff551a3a1a | 131 | } |
gtk2k | 0:98ff551a3a1a | 132 | printf("data length:%d\n", dataLen); |
gtk2k | 0:98ff551a3a1a | 133 | buff[6 + dataLen] = 0; |
gtk2k | 0:98ff551a3a1a | 134 | if (opcode == 1) { |
gtk2k | 0:98ff551a3a1a | 135 | printf("received data:%s\n", buff + 6); |
gtk2k | 0:98ff551a3a1a | 136 | char sendData[2 + dataLen + 1]; |
gtk2k | 0:98ff551a3a1a | 137 | sendData[0] = buff[0]; |
gtk2k | 0:98ff551a3a1a | 138 | sendData[1] = buff[1] & 0x7f; |
gtk2k | 0:98ff551a3a1a | 139 | for (i = 0; i < dataLen; i++) { |
gtk2k | 0:98ff551a3a1a | 140 | sendData[2 + i] = buff[6 + i]; |
gtk2k | 0:98ff551a3a1a | 141 | } |
gtk2k | 0:98ff551a3a1a | 142 | sendData[2 + dataLen] = 0; |
gtk2k | 0:98ff551a3a1a | 143 | sock.send_all(sendData, 2 + dataLen); |
gtk2k | 0:98ff551a3a1a | 144 | } else if (opcode == 2) { |
gtk2k | 0:98ff551a3a1a | 145 | led1 = buff[6 + 0]; |
gtk2k | 0:98ff551a3a1a | 146 | led2 = buff[6 + 1]; |
gtk2k | 0:98ff551a3a1a | 147 | led3 = buff[6 + 2]; |
gtk2k | 0:98ff551a3a1a | 148 | led4 = buff[6 + 3]; |
gtk2k | 0:98ff551a3a1a | 149 | } |
gtk2k | 0:98ff551a3a1a | 150 | break; |
gtk2k | 0:98ff551a3a1a | 151 | } |
gtk2k | 0:98ff551a3a1a | 152 | } |
gtk2k | 0:98ff551a3a1a | 153 | |
gtk2k | 0:98ff551a3a1a | 154 | sock.close(); |
gtk2k | 0:98ff551a3a1a | 155 | eth.disconnect(); |
gtk2k | 0:98ff551a3a1a | 156 | while(1) {} |
gtk2k | 0:98ff551a3a1a | 157 | } |
gtk2k | 0:98ff551a3a1a | 158 |