The library with which to configure a Web Socket Server on a Mbed. This lib was coded by a day at least one year before when this description is written. It will be updated adopting mbed os 5.
WS_SERVER.cpp@1:73f2f67d1732, 2018-03-03 (annotated)
- Committer:
- aktk
- Date:
- Sat Mar 03 18:47:34 2018 +0000
- Revision:
- 1:73f2f67d1732
- Parent:
- 0:86a479dd1814
Private (1 vs 1) ws-com seems to have been implemented on Dec 08, 2016.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
aktk | 0:86a479dd1814 | 1 | #include "WS_SERVER.h" |
aktk | 0:86a479dd1814 | 2 | #define DEBUG |
aktk | 0:86a479dd1814 | 3 | |
aktk | 0:86a479dd1814 | 4 | //Serial wspc(USBTX, USBRX); |
aktk | 0:86a479dd1814 | 5 | namespace WS_SERVER |
aktk | 0:86a479dd1814 | 6 | { |
aktk | 0:86a479dd1814 | 7 | void DEBUG_PRINT_LINE(const char* arg_line) |
aktk | 0:86a479dd1814 | 8 | { |
aktk | 0:86a479dd1814 | 9 | #ifdef DEBUG |
aktk | 0:86a479dd1814 | 10 | printf("(WSS) "); |
aktk | 0:86a479dd1814 | 11 | printf(arg_line); |
aktk | 0:86a479dd1814 | 12 | printf("\r\n"); |
aktk | 0:86a479dd1814 | 13 | #endif |
aktk | 0:86a479dd1814 | 14 | } |
aktk | 0:86a479dd1814 | 15 | template<typename T> |
aktk | 0:86a479dd1814 | 16 | void DEBUG_PRINT_LINE(const char* arg_line, T arg_t) |
aktk | 0:86a479dd1814 | 17 | { |
aktk | 0:86a479dd1814 | 18 | #ifdef DEBUG |
aktk | 0:86a479dd1814 | 19 | printf("(WSS) "); |
aktk | 0:86a479dd1814 | 20 | printf(arg_line, arg_t); |
aktk | 0:86a479dd1814 | 21 | printf("\r\n"); |
aktk | 0:86a479dd1814 | 22 | #endif |
aktk | 0:86a479dd1814 | 23 | } |
aktk | 0:86a479dd1814 | 24 | template<typename T1, typename T2> |
aktk | 0:86a479dd1814 | 25 | void DEBUG_PRINT_LINE(const char* arg_line, T1 arg_t1, T2 arg_t2) |
aktk | 0:86a479dd1814 | 26 | { |
aktk | 0:86a479dd1814 | 27 | #ifdef DEBUG |
aktk | 0:86a479dd1814 | 28 | printf("(WSS) "); |
aktk | 0:86a479dd1814 | 29 | printf(arg_line, arg_t1, arg_t2); |
aktk | 0:86a479dd1814 | 30 | printf("\r\n"); |
aktk | 0:86a479dd1814 | 31 | #endif |
aktk | 0:86a479dd1814 | 32 | } |
aktk | 1:73f2f67d1732 | 33 | template<typename T1, typename T2, typename T3> |
aktk | 1:73f2f67d1732 | 34 | void DEBUG_PRINT_LINE(const char* arg_line, T1 arg_t1, T2 arg_t2, T3 arg_t3) |
aktk | 1:73f2f67d1732 | 35 | { |
aktk | 1:73f2f67d1732 | 36 | #ifdef DEBUG |
aktk | 1:73f2f67d1732 | 37 | printf("(WSS) "); |
aktk | 1:73f2f67d1732 | 38 | printf(arg_line, arg_t1, arg_t2, arg_t3); |
aktk | 1:73f2f67d1732 | 39 | printf("\r\n"); |
aktk | 1:73f2f67d1732 | 40 | #endif |
aktk | 1:73f2f67d1732 | 41 | } |
aktk | 0:86a479dd1814 | 42 | } |
aktk | 0:86a479dd1814 | 43 | using namespace WS_SERVER; |
aktk | 0:86a479dd1814 | 44 | |
aktk | 0:86a479dd1814 | 45 | WSS::WSS() |
aktk | 0:86a479dd1814 | 46 | :m_RxBufferSize(1024) |
aktk | 0:86a479dd1814 | 47 | ,m_PortNumber(8085) |
aktk | 0:86a479dd1814 | 48 | { |
aktk | 0:86a479dd1814 | 49 | m_ListeningFlag = (false); |
aktk | 1:73f2f67d1732 | 50 | m_RxBuffer = new uint8_t[1024]; |
aktk | 0:86a479dd1814 | 51 | m_restAppDataLen = 0; |
aktk | 0:86a479dd1814 | 52 | |
aktk | 0:86a479dd1814 | 53 | m_DiscontiuanceFlag = false; |
aktk | 0:86a479dd1814 | 54 | m_EODFlag = false; |
aktk | 0:86a479dd1814 | 55 | } |
aktk | 0:86a479dd1814 | 56 | |
aktk | 0:86a479dd1814 | 57 | WSS::WSS(uint32_t arg_RxBufferSize, uint32_t arg_PortNumber) |
aktk | 0:86a479dd1814 | 58 | :m_RxBufferSize(arg_RxBufferSize) |
aktk | 0:86a479dd1814 | 59 | ,m_PortNumber(arg_PortNumber) |
aktk | 0:86a479dd1814 | 60 | { |
aktk | 0:86a479dd1814 | 61 | m_ListeningFlag = (false); |
aktk | 1:73f2f67d1732 | 62 | m_RxBuffer = new uint8_t[arg_RxBufferSize]; |
aktk | 0:86a479dd1814 | 63 | m_restAppDataLen = 0; |
aktk | 0:86a479dd1814 | 64 | |
aktk | 0:86a479dd1814 | 65 | m_DiscontiuanceFlag = false; |
aktk | 0:86a479dd1814 | 66 | m_EODFlag = false; |
aktk | 0:86a479dd1814 | 67 | } |
aktk | 0:86a479dd1814 | 68 | |
aktk | 0:86a479dd1814 | 69 | WSS::~WSS() |
aktk | 0:86a479dd1814 | 70 | { |
aktk | 0:86a479dd1814 | 71 | delete(m_RxBuffer); |
aktk | 0:86a479dd1814 | 72 | } |
aktk | 0:86a479dd1814 | 73 | |
aktk | 0:86a479dd1814 | 74 | bool WSS::init() |
aktk | 0:86a479dd1814 | 75 | { |
aktk | 0:86a479dd1814 | 76 | DEBUG_PRINT_LINE("DEBUG MODE"); |
aktk | 0:86a479dd1814 | 77 | |
aktk | 0:86a479dd1814 | 78 | // Ethernet Initialization |
aktk | 0:86a479dd1814 | 79 | if(m_eth.init()) { |
aktk | 0:86a479dd1814 | 80 | printf("(WSS) Error!@EthernetInterface::init()\r\n"); |
aktk | 0:86a479dd1814 | 81 | return false; |
aktk | 0:86a479dd1814 | 82 | } |
aktk | 0:86a479dd1814 | 83 | // Ethernet Connecting setup |
aktk | 0:86a479dd1814 | 84 | if(m_eth.connect()) { |
aktk | 0:86a479dd1814 | 85 | printf("(WSS) Error!@EthernetInterface::connect()\r\n"); |
aktk | 0:86a479dd1814 | 86 | return false; |
aktk | 0:86a479dd1814 | 87 | } else { |
aktk | 0:86a479dd1814 | 88 | printf("(WSS) IP Address is %s\r\n", m_eth.getIPAddress()); |
aktk | 0:86a479dd1814 | 89 | } |
aktk | 0:86a479dd1814 | 90 | |
aktk | 0:86a479dd1814 | 91 | |
aktk | 0:86a479dd1814 | 92 | // TCP Socket setup |
aktk | 0:86a479dd1814 | 93 | // To open Server-side PORT |
aktk | 0:86a479dd1814 | 94 | if(m_tcpsvr.bind(m_PortNumber)< 0) { |
aktk | 0:86a479dd1814 | 95 | printf("(WSS) Error!@TCPSocketServer::bind()\r\n"); |
aktk | 0:86a479dd1814 | 96 | return false; |
aktk | 0:86a479dd1814 | 97 | } else { |
aktk | 0:86a479dd1814 | 98 | printf("(WSS) TCP Server has bounden!\r\n"); |
aktk | 0:86a479dd1814 | 99 | } |
aktk | 0:86a479dd1814 | 100 | // Server start listening Request from a web browser. |
aktk | 0:86a479dd1814 | 101 | if(m_tcpsvr.listen(1) < 0) { |
aktk | 0:86a479dd1814 | 102 | printf("(WSS) TCP server listen failed.\r\n"); |
aktk | 0:86a479dd1814 | 103 | return false; |
aktk | 0:86a479dd1814 | 104 | } else { |
aktk | 0:86a479dd1814 | 105 | m_ListeningFlag = true; |
aktk | 0:86a479dd1814 | 106 | printf("(WSS) TCP server is listening...\r\n"); |
aktk | 0:86a479dd1814 | 107 | } |
aktk | 0:86a479dd1814 | 108 | |
aktk | 0:86a479dd1814 | 109 | return true; |
aktk | 0:86a479dd1814 | 110 | } |
aktk | 0:86a479dd1814 | 111 | |
aktk | 0:86a479dd1814 | 112 | bool WSS::isListening() |
aktk | 0:86a479dd1814 | 113 | { |
aktk | 0:86a479dd1814 | 114 | return m_ListeningFlag; |
aktk | 0:86a479dd1814 | 115 | } |
aktk | 0:86a479dd1814 | 116 | |
aktk | 0:86a479dd1814 | 117 | void WSS::run() |
aktk | 0:86a479dd1814 | 118 | { |
aktk | 0:86a479dd1814 | 119 | DigitalOut led3(LED3); |
aktk | 0:86a479dd1814 | 120 | DigitalOut led4(LED4); |
aktk | 0:86a479dd1814 | 121 | |
aktk | 0:86a479dd1814 | 122 | while (m_ListeningFlag) { |
aktk | 0:86a479dd1814 | 123 | led3 = true; |
aktk | 0:86a479dd1814 | 124 | // blocking mode (never timeout) |
aktk | 0:86a479dd1814 | 125 | // waiting client connection |
aktk | 0:86a479dd1814 | 126 | printf("(WSS) Waiting Connection\r\n"); |
aktk | 0:86a479dd1814 | 127 | if(m_tcpsvr.accept(m_tcpcon) < 0) { |
aktk | 0:86a479dd1814 | 128 | printf("(WSS) Failed to accept connection.\r\n"); |
aktk | 0:86a479dd1814 | 129 | } else { |
aktk | 0:86a479dd1814 | 130 | printf("(WSS) Connection Success!\r\n"); |
aktk | 0:86a479dd1814 | 131 | printf("(WSS) IP: %s\r\n",m_tcpcon.get_address()); |
aktk | 0:86a479dd1814 | 132 | |
aktk | 0:86a479dd1814 | 133 | led4 = true; |
aktk | 0:86a479dd1814 | 134 | } |
aktk | 0:86a479dd1814 | 135 | // When conected |
aktk | 0:86a479dd1814 | 136 | // Main WSS Communication---------------------------------- |
aktk | 0:86a479dd1814 | 137 | while(m_tcpcon.is_connected()) { |
aktk | 0:86a479dd1814 | 138 | DEBUG_PRINT_LINE("(WSS) Connected"); |
aktk | 1:73f2f67d1732 | 139 | if(handshake()) |
aktk | 1:73f2f67d1732 | 140 | while(!m_DiscontiuanceFlag)rxMessage(); |
aktk | 0:86a479dd1814 | 141 | DEBUG_PRINT_LINE("(WSS) Closing"); |
aktk | 0:86a479dd1814 | 142 | // txClosing(1002, "RecievedNot Masked Data"); |
aktk | 0:86a479dd1814 | 143 | } |
aktk | 0:86a479dd1814 | 144 | // ^^^^^^^^^^^^^^^^^^^^^^---------------------------------- |
aktk | 0:86a479dd1814 | 145 | printf("(WSS) Close connection.\r\ntcp server is listening...\r\n"); |
aktk | 0:86a479dd1814 | 146 | m_tcpcon.close(); |
aktk | 0:86a479dd1814 | 147 | led4 = false; |
aktk | 0:86a479dd1814 | 148 | |
aktk | 0:86a479dd1814 | 149 | // When any critical errors are occured. |
aktk | 0:86a479dd1814 | 150 | //if(/*anyerror*/) m_ListeningFlag = false; |
aktk | 0:86a479dd1814 | 151 | } |
aktk | 0:86a479dd1814 | 152 | m_tcpsvr.close(); |
aktk | 0:86a479dd1814 | 153 | led3 = false; |
aktk | 0:86a479dd1814 | 154 | while(1); |
aktk | 0:86a479dd1814 | 155 | } |
aktk | 0:86a479dd1814 | 156 | |
aktk | 0:86a479dd1814 | 157 | bool WSS::isReadable() |
aktk | 0:86a479dd1814 | 158 | { |
aktk | 0:86a479dd1814 | 159 | if(m_restAppDataLen > 0) |
aktk | 0:86a479dd1814 | 160 | return true; |
aktk | 0:86a479dd1814 | 161 | else |
aktk | 0:86a479dd1814 | 162 | return false; |
aktk | 0:86a479dd1814 | 163 | } |
aktk | 0:86a479dd1814 | 164 | |
aktk | 0:86a479dd1814 | 165 | int8_t WSS::getRxData() |
aktk | 0:86a479dd1814 | 166 | { |
aktk | 0:86a479dd1814 | 167 | if(m_restAppDataLen > 0) { |
aktk | 0:86a479dd1814 | 168 | int l_index = m_ApplicationLen - m_restAppDataLen; |
aktk | 0:86a479dd1814 | 169 | m_restAppDataLen--; |
aktk | 0:86a479dd1814 | 170 | return m_PayloadData[l_index] ^ m_Masking_key[l_index % 4]; |
aktk | 0:86a479dd1814 | 171 | } else |
aktk | 0:86a479dd1814 | 172 | return 0x00; |
aktk | 0:86a479dd1814 | 173 | } |
aktk | 0:86a479dd1814 | 174 | |
aktk | 0:86a479dd1814 | 175 | void WSS::discardRxBuffer() |
aktk | 0:86a479dd1814 | 176 | { |
aktk | 0:86a479dd1814 | 177 | m_RxBuffer = NULL; |
aktk | 0:86a479dd1814 | 178 | m_restAppDataLen = 0; |
aktk | 0:86a479dd1814 | 179 | } |
aktk | 0:86a479dd1814 | 180 | |
aktk | 0:86a479dd1814 | 181 | void WSS::txPing() |
aktk | 0:86a479dd1814 | 182 | { |
aktk | 0:86a479dd1814 | 183 | DEBUG_PRINT_LINE("Ping Pong Debug"); |
aktk | 0:86a479dd1814 | 184 | } |
aktk | 0:86a479dd1814 | 185 | int8_t WSS::rxMessage() |
aktk | 0:86a479dd1814 | 186 | { |
aktk | 0:86a479dd1814 | 187 | int64_t l_RxDataLen = 0; |
aktk | 0:86a479dd1814 | 188 | int64_t l_MesuredDataLen = 0; |
aktk | 0:86a479dd1814 | 189 | |
aktk | 0:86a479dd1814 | 190 | if(isReadable()) return -1; |
aktk | 0:86a479dd1814 | 191 | // |
aktk | 0:86a479dd1814 | 192 | // A (part of) data is recieved here. |
aktk | 0:86a479dd1814 | 193 | // |
aktk | 0:86a479dd1814 | 194 | m_DiscontiuanceFlag = false; |
aktk | 0:86a479dd1814 | 195 | switch(l_RxDataLen = m_tcpcon.receive((char*)m_RxBuffer, m_RxBufferSize)) { |
aktk | 0:86a479dd1814 | 196 | case 0: |
aktk | 0:86a479dd1814 | 197 | DEBUG_PRINT_LINE("Recieved buffer is empty."); |
aktk | 0:86a479dd1814 | 198 | m_DiscontiuanceFlag = true; |
aktk | 0:86a479dd1814 | 199 | break; |
aktk | 0:86a479dd1814 | 200 | case -1: |
aktk | 0:86a479dd1814 | 201 | DEBUG_PRINT_LINE("Failed to read data from client."); |
aktk | 0:86a479dd1814 | 202 | m_DiscontiuanceFlag = true; |
aktk | 0:86a479dd1814 | 203 | break; |
aktk | 0:86a479dd1814 | 204 | default: |
aktk | 0:86a479dd1814 | 205 | DEBUG_PRINT_LINE("Massege Has Received"); |
aktk | 0:86a479dd1814 | 206 | break; |
aktk | 0:86a479dd1814 | 207 | } |
aktk | 0:86a479dd1814 | 208 | DEBUG_PRINT_LINE("Data size: %d Bytes", strlen((char*) m_RxBuffer)); |
aktk | 0:86a479dd1814 | 209 | for(int i = 0; i < strlen((char*) m_RxBuffer); i++) |
aktk | 1:73f2f67d1732 | 210 | DEBUG_PRINT_LINE("Data%5d: %2x (%3d)", i, m_RxBuffer[i], m_RxBuffer[i]); |
aktk | 0:86a479dd1814 | 211 | // |
aktk | 0:86a479dd1814 | 212 | // Data Parsing |
aktk | 0:86a479dd1814 | 213 | // |
aktk | 0:86a479dd1814 | 214 | l_MesuredDataLen++; |
aktk | 0:86a479dd1814 | 215 | m_FIN_RSV = m_RxBuffer[0] >> 4; |
aktk | 0:86a479dd1814 | 216 | //If FIN is 1, the data is the last of a sequence. |
aktk | 0:86a479dd1814 | 217 | if(m_FIN_RSV >> 3) |
aktk | 0:86a479dd1814 | 218 | m_EODFlag = true; |
aktk | 0:86a479dd1814 | 219 | //IF RSV1, 2, or 3 is 1, communication should be discontinued, because there is no negotiation. |
aktk | 0:86a479dd1814 | 220 | if(m_FIN_RSV & 0x07) |
aktk | 0:86a479dd1814 | 221 | m_DiscontiuanceFlag = true; |
aktk | 0:86a479dd1814 | 222 | m_Opcode = m_RxBuffer[0] & 0x0F; |
aktk | 0:86a479dd1814 | 223 | switch((OpCode)m_Opcode) { |
aktk | 0:86a479dd1814 | 224 | case cont: |
aktk | 0:86a479dd1814 | 225 | case txt: |
aktk | 0:86a479dd1814 | 226 | case bin: |
aktk | 0:86a479dd1814 | 227 | case close: |
aktk | 0:86a479dd1814 | 228 | case ping: |
aktk | 0:86a479dd1814 | 229 | case pong: { |
aktk | 0:86a479dd1814 | 230 | m_FrameOpcode = (OpCode)m_Opcode; |
aktk | 0:86a479dd1814 | 231 | break; |
aktk | 0:86a479dd1814 | 232 | } |
aktk | 0:86a479dd1814 | 233 | default: { |
aktk | 0:86a479dd1814 | 234 | m_DiscontiuanceFlag = true; |
aktk | 0:86a479dd1814 | 235 | break; |
aktk | 0:86a479dd1814 | 236 | } |
aktk | 0:86a479dd1814 | 237 | } |
aktk | 0:86a479dd1814 | 238 | DEBUG_PRINT_LINE("Data parsing ... 1/3"); |
aktk | 0:86a479dd1814 | 239 | DEBUG_PRINT_LINE("FIN RSV: %x", m_FIN_RSV); |
aktk | 0:86a479dd1814 | 240 | DEBUG_PRINT_LINE("Opcode : %x", m_Opcode); |
aktk | 0:86a479dd1814 | 241 | l_MesuredDataLen++; |
aktk | 0:86a479dd1814 | 242 | // サーバは、マスクされていないフレームを受信した際には,接続を close しなければならない。 |
aktk | 0:86a479dd1814 | 243 | // この場合,サーバは、 7.4.1 節 の定義に従って,ステータスコード 1002 (プロトコルエラー)を伴う Close フレームを送信してもよい。 |
aktk | 0:86a479dd1814 | 244 | m_Mask = m_RxBuffer[1] >> 7; |
aktk | 0:86a479dd1814 | 245 | if(m_Mask == 0) { |
aktk | 0:86a479dd1814 | 246 | m_DiscontiuanceFlag = true; |
aktk | 0:86a479dd1814 | 247 | } |
aktk | 1:73f2f67d1732 | 248 | DEBUG_PRINT_LINE("Mask : %x", m_Opcode); |
aktk | 1:73f2f67d1732 | 249 | m_PayloadLen = (uint64_t)(m_RxBuffer[1] & 0x7f); |
aktk | 0:86a479dd1814 | 250 | if(m_PayloadLen < 0x07e) { |
aktk | 0:86a479dd1814 | 251 | l_MesuredDataLen += m_PayloadLen; |
aktk | 0:86a479dd1814 | 252 | // Buffer [2] [3] [4] [5] have Masking_Key |
aktk | 0:86a479dd1814 | 253 | l_MesuredDataLen += 4; |
aktk | 0:86a479dd1814 | 254 | if(m_Mask) for(int i = 0; i < 4; i++) m_Masking_key[i] = (m_RxBuffer[2 + i]); |
aktk | 0:86a479dd1814 | 255 | // The Head of Payload data is at buffer[6] |
aktk | 0:86a479dd1814 | 256 | m_PayloadData = m_RxBuffer + 6; |
aktk | 1:73f2f67d1732 | 257 | DEBUG_PRINT_LINE("PL Len : %x", (uint32_t)m_PayloadLen); |
aktk | 0:86a479dd1814 | 258 | } else if (m_PayloadLen == 0x07e) { |
aktk | 0:86a479dd1814 | 259 | l_MesuredDataLen += m_PayloadLen; |
aktk | 0:86a479dd1814 | 260 | // Two succeeded bytes buffer [2] and [3] have SubPayload |
aktk | 0:86a479dd1814 | 261 | l_MesuredDataLen += 2; |
aktk | 0:86a479dd1814 | 262 | m_PayloadLen = (uint64_t)((m_RxBuffer[2] << 8)|(m_RxBuffer[3]&0xff)); |
aktk | 0:86a479dd1814 | 263 | // Buffer [4] [5] [6] [7] have Masking_Key |
aktk | 0:86a479dd1814 | 264 | l_MesuredDataLen += 4; |
aktk | 0:86a479dd1814 | 265 | if(m_Mask) for(int i = 0; i < 4; i++) m_Masking_key[i] = (m_RxBuffer[4 + i]); |
aktk | 0:86a479dd1814 | 266 | // The Head of Payload data is at buffer[8] |
aktk | 0:86a479dd1814 | 267 | m_PayloadData = m_RxBuffer + 8; |
aktk | 1:73f2f67d1732 | 268 | DEBUG_PRINT_LINE("PL Len : %x", (uint32_t)m_PayloadLen); |
aktk | 0:86a479dd1814 | 269 | } else if (m_PayloadLen == 0x07f) { |
aktk | 0:86a479dd1814 | 270 | l_MesuredDataLen += m_PayloadLen; |
aktk | 0:86a479dd1814 | 271 | // Eight succeeded bytes buffer [2], [3], [4], [5], [6], [7], [8], and [9] have SubPayload |
aktk | 0:86a479dd1814 | 272 | l_MesuredDataLen += 8; |
aktk | 0:86a479dd1814 | 273 | m_PayloadLen = (uint64_t)(m_RxBuffer[2] & 0xff); |
aktk | 0:86a479dd1814 | 274 | for(int i = 0; i < 7; i++) |
aktk | 0:86a479dd1814 | 275 | m_PayloadLen = (uint64_t)((m_PayloadLen << 8) | (m_RxBuffer[3 + i] & 0xff)); |
aktk | 0:86a479dd1814 | 276 | l_MesuredDataLen += 4; |
aktk | 0:86a479dd1814 | 277 | // Buffer [10] [11] [12] [13] have Masking_Key |
aktk | 0:86a479dd1814 | 278 | if(m_Mask) for(int i = 0; i < 4; i++) m_Masking_key[i] = (m_RxBuffer[10 + i]); |
aktk | 0:86a479dd1814 | 279 | // The Head of Payload data is at buffer[14] |
aktk | 0:86a479dd1814 | 280 | m_PayloadData = m_RxBuffer + 14; |
aktk | 1:73f2f67d1732 | 281 | DEBUG_PRINT_LINE("PL Len : %x%x", (uint32_t)(m_PayloadLen>>32),(uint32_t)(m_PayloadLen&0xffffffff)); |
aktk | 0:86a479dd1814 | 282 | } |
aktk | 0:86a479dd1814 | 283 | DEBUG_PRINT_LINE("Data parsing ... 2/3"); |
aktk | 1:73f2f67d1732 | 284 | |
aktk | 0:86a479dd1814 | 285 | // Because there is no negotiation of Extention, Extention data is regarded as none. |
aktk | 0:86a479dd1814 | 286 | m_ExtensionLen = 0; |
aktk | 0:86a479dd1814 | 287 | m_ApplicationLen = m_PayloadLen - m_ExtensionLen; |
aktk | 0:86a479dd1814 | 288 | m_restAppDataLen = m_ApplicationLen; |
aktk | 0:86a479dd1814 | 289 | DEBUG_PRINT_LINE("Data parsing ... 3/3"); |
aktk | 1:73f2f67d1732 | 290 | DEBUG_PRINT_LINE("Application Data Len: %08x%08x Byte", (uint32_t)(m_ApplicationLen>>32), (uint32_t)(m_ApplicationLen &0xffffffff)); |
aktk | 1:73f2f67d1732 | 291 | |
aktk | 0:86a479dd1814 | 292 | if(l_MesuredDataLen != l_RxDataLen) { |
aktk | 0:86a479dd1814 | 293 | m_DiscontiuanceFlag = true; |
aktk | 0:86a479dd1814 | 294 | } |
aktk | 0:86a479dd1814 | 295 | |
aktk | 0:86a479dd1814 | 296 | return m_DiscontiuanceFlag ? 1 : 0; |
aktk | 0:86a479dd1814 | 297 | } |
aktk | 0:86a479dd1814 | 298 | |
aktk | 0:86a479dd1814 | 299 | bool WSS::handshake() |
aktk | 0:86a479dd1814 | 300 | { |
aktk | 0:86a479dd1814 | 301 | char* httpmethod = NULL; |
aktk | 0:86a479dd1814 | 302 | char* filepath = NULL; |
aktk | 0:86a479dd1814 | 303 | char* http_ver = NULL; |
aktk | 0:86a479dd1814 | 304 | char* header_field_name = NULL; |
aktk | 0:86a479dd1814 | 305 | char* header_field_val = NULL; |
aktk | 0:86a479dd1814 | 306 | |
aktk | 0:86a479dd1814 | 307 | // |
aktk | 0:86a479dd1814 | 308 | // Handshake HTTP Request Analysis |
aktk | 0:86a479dd1814 | 309 | // |
aktk | 0:86a479dd1814 | 310 | switch(m_tcpcon.receive((char*)m_RxBuffer, 1023)) { |
aktk | 0:86a479dd1814 | 311 | case 0: |
aktk | 0:86a479dd1814 | 312 | DEBUG_PRINT_LINE("Recieved buffer is empty."); |
aktk | 0:86a479dd1814 | 313 | m_msger.setStatusLine(400, "No Request"); |
aktk | 0:86a479dd1814 | 314 | httpmethod = NULL; |
aktk | 0:86a479dd1814 | 315 | filepath = NULL; |
aktk | 0:86a479dd1814 | 316 | http_ver = NULL; |
aktk | 0:86a479dd1814 | 317 | break; |
aktk | 0:86a479dd1814 | 318 | case -1: |
aktk | 0:86a479dd1814 | 319 | DEBUG_PRINT_LINE("Failed to read data from client."); |
aktk | 0:86a479dd1814 | 320 | m_msger.setStatusLine(500, "Internal Server Error"); |
aktk | 0:86a479dd1814 | 321 | httpmethod = NULL; |
aktk | 0:86a479dd1814 | 322 | filepath = NULL; |
aktk | 0:86a479dd1814 | 323 | http_ver = NULL; |
aktk | 0:86a479dd1814 | 324 | break; |
aktk | 0:86a479dd1814 | 325 | default: |
aktk | 0:86a479dd1814 | 326 | DEBUG_PRINT_LINE("Recieved Data: %d\r\n-->",strlen((char*)m_RxBuffer)); |
aktk | 0:86a479dd1814 | 327 | DEBUG_PRINT_LINE("%.*s[End of Request]", strlen((char*)m_RxBuffer),(char*)m_RxBuffer); |
aktk | 0:86a479dd1814 | 328 | // get HTTP method, File path, HTTP version |
aktk | 0:86a479dd1814 | 329 | httpmethod = strtok((char*)m_RxBuffer," "); |
aktk | 0:86a479dd1814 | 330 | filepath = strtok(NULL, " "); |
aktk | 0:86a479dd1814 | 331 | http_ver = strtok(NULL, "\r\n"); |
aktk | 0:86a479dd1814 | 332 | DEBUG_PRINT_LINE("httpmethod: %s", httpmethod); |
aktk | 0:86a479dd1814 | 333 | DEBUG_PRINT_LINE("file path: %s", filepath); |
aktk | 0:86a479dd1814 | 334 | DEBUG_PRINT_LINE("http ver : %s", http_ver); |
aktk | 0:86a479dd1814 | 335 | break; |
aktk | 0:86a479dd1814 | 336 | } |
aktk | 0:86a479dd1814 | 337 | |
aktk | 0:86a479dd1814 | 338 | // |
aktk | 0:86a479dd1814 | 339 | // Handshake Response Form |
aktk | 0:86a479dd1814 | 340 | // |
aktk | 0:86a479dd1814 | 341 | if (strcmp(httpmethod,"GET") == 0 ) { |
aktk | 0:86a479dd1814 | 342 | DEBUG_PRINT_LINE("GET request incomming."); |
aktk | 0:86a479dd1814 | 343 | // Define behaviour of server according to Request Header lines |
aktk | 0:86a479dd1814 | 344 | // Apply request header field to response header field |
aktk | 0:86a479dd1814 | 345 | char* field_Connection = NULL; |
aktk | 0:86a479dd1814 | 346 | char* field_Upgrade = NULL; |
aktk | 0:86a479dd1814 | 347 | char* field_Sec_WebSocket_Key = NULL; |
aktk | 0:86a479dd1814 | 348 | char* field_Sec_WebSocket_Version = NULL; |
aktk | 0:86a479dd1814 | 349 | char* field_Origin = NULL; |
aktk | 0:86a479dd1814 | 350 | do { |
aktk | 0:86a479dd1814 | 351 | //Analyze the header feilds |
aktk | 0:86a479dd1814 | 352 | header_field_name = strtok(NULL, ":"); |
aktk | 0:86a479dd1814 | 353 | header_field_name++; |
aktk | 0:86a479dd1814 | 354 | header_field_val = strtok(NULL, "\r\n"); |
aktk | 0:86a479dd1814 | 355 | header_field_val++; |
aktk | 0:86a479dd1814 | 356 | |
aktk | 0:86a479dd1814 | 357 | if(header_field_name - 1 != NULL) { |
aktk | 0:86a479dd1814 | 358 | if(!strcmp(header_field_name, "Connection")) { |
aktk | 0:86a479dd1814 | 359 | field_Connection = header_field_val; |
aktk | 0:86a479dd1814 | 360 | } else if(!strcmp(header_field_name, "Upgrade")) { |
aktk | 0:86a479dd1814 | 361 | field_Upgrade = header_field_val; |
aktk | 0:86a479dd1814 | 362 | } else if(!strcmp(header_field_name, "Sec-WebSocket-Key") ) { |
aktk | 0:86a479dd1814 | 363 | field_Sec_WebSocket_Key = header_field_val; |
aktk | 0:86a479dd1814 | 364 | } else if(!strcmp(header_field_name, "Sec-WebSocket-Version") ) { |
aktk | 0:86a479dd1814 | 365 | field_Sec_WebSocket_Version = header_field_val; |
aktk | 0:86a479dd1814 | 366 | } else if(!strcmp(header_field_name, "Origin") ) { |
aktk | 0:86a479dd1814 | 367 | field_Origin = header_field_val; |
aktk | 0:86a479dd1814 | 368 | } |
aktk | 0:86a479dd1814 | 369 | DEBUG_PRINT_LINE("*header_field_name adr: %d %s", header_field_name - 1, header_field_name); |
aktk | 0:86a479dd1814 | 370 | DEBUG_PRINT_LINE(" header_field_val adr: %d %s", header_field_val - 1, header_field_val); |
aktk | 0:86a479dd1814 | 371 | } else { |
aktk | 0:86a479dd1814 | 372 | break; |
aktk | 0:86a479dd1814 | 373 | } |
aktk | 0:86a479dd1814 | 374 | } while(1); |
aktk | 0:86a479dd1814 | 375 | |
aktk | 0:86a479dd1814 | 376 | DEBUG_PRINT_LINE("Parsing has been done"); |
aktk | 0:86a479dd1814 | 377 | // if the request is to switching to the WebSocket Server |
aktk | 0:86a479dd1814 | 378 | if(!strcmp((char*)field_Connection, "Upgrade")) { |
aktk | 0:86a479dd1814 | 379 | if( !strcmp(field_Upgrade, "websocket") && |
aktk | 0:86a479dd1814 | 380 | field_Sec_WebSocket_Key != NULL && |
aktk | 0:86a479dd1814 | 381 | !strcmp(field_Sec_WebSocket_Version, "13") && |
aktk | 0:86a479dd1814 | 382 | field_Origin != NULL) { |
aktk | 0:86a479dd1814 | 383 | DEBUG_PRINT_LINE("Prepering for Update"); |
aktk | 0:86a479dd1814 | 384 | // |
aktk | 0:86a479dd1814 | 385 | // Calcurate the key |
aktk | 0:86a479dd1814 | 386 | // |
aktk | 0:86a479dd1814 | 387 | // concat the input key and the str. |
aktk | 0:86a479dd1814 | 388 | unsigned char SecWebSocketAccept[256]; |
aktk | 0:86a479dd1814 | 389 | sprintf((char*)SecWebSocketAccept, "%s%s", field_Sec_WebSocket_Key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); |
aktk | 0:86a479dd1814 | 390 | DEBUG_PRINT_LINE("Appended Key: %s", (char*)SecWebSocketAccept); |
aktk | 0:86a479dd1814 | 391 | // evaluate SHA1 |
aktk | 0:86a479dd1814 | 392 | unsigned char sha1Output[20]; |
aktk | 0:86a479dd1814 | 393 | sha1(SecWebSocketAccept, strlen((char*)SecWebSocketAccept), sha1Output); |
aktk | 0:86a479dd1814 | 394 | DEBUG_PRINT_LINE("SHA1 hashed Key:"); |
aktk | 0:86a479dd1814 | 395 | for(int i = 0; i < 20; i++) DEBUG_PRINT_LINE("%x", sha1Output[i]); |
aktk | 0:86a479dd1814 | 396 | // encode the hash into base 64 |
aktk | 0:86a479dd1814 | 397 | { |
aktk | 0:86a479dd1814 | 398 | size_t sizeofbuffer = strlen((char*)SecWebSocketAccept); |
aktk | 0:86a479dd1814 | 399 | if(base64_encode(SecWebSocketAccept, &sizeofbuffer, sha1Output, 20) != 0)DEBUG_PRINT_LINE("something wrong@base64_encode"); |
aktk | 0:86a479dd1814 | 400 | DEBUG_PRINT_LINE((char*)SecWebSocketAccept); |
aktk | 0:86a479dd1814 | 401 | } |
aktk | 0:86a479dd1814 | 402 | // --- end of culculation of the key --- |
aktk | 0:86a479dd1814 | 403 | // |
aktk | 0:86a479dd1814 | 404 | // Format HTTP response of ACK |
aktk | 0:86a479dd1814 | 405 | // |
aktk | 0:86a479dd1814 | 406 | DEBUG_PRINT_LINE("Communication Protocol will be Upgraded to Websocket!"); |
aktk | 0:86a479dd1814 | 407 | m_msger.resetHeader(); |
aktk | 0:86a479dd1814 | 408 | m_msger.setStatusLine(101, "Switching Protocols"); |
aktk | 0:86a479dd1814 | 409 | if(m_msger.setHeaderField("Connection", "Upgrade")) DEBUG_PRINT_LINE("buffer over flow@ResposeMessenger"); |
aktk | 0:86a479dd1814 | 410 | if(m_msger.setHeaderField("Upgrade", "websocket")) DEBUG_PRINT_LINE("buffer over flow@ResposeMessenger"); |
aktk | 0:86a479dd1814 | 411 | if(m_msger.setHeaderField("Sec-WebSocket-Accept", (char*)SecWebSocketAccept)) DEBUG_PRINT_LINE("buffer over flow@ResposeMessenger"); |
aktk | 0:86a479dd1814 | 412 | if(m_msger.setHeaderField("Access-Control-Allow-Origin", m_tcpcon.get_address())) DEBUG_PRINT_LINE("buffer over flow@ResposeMessenger"); |
aktk | 0:86a479dd1814 | 413 | // --- end of formatting --- |
aktk | 0:86a479dd1814 | 414 | } else { |
aktk | 0:86a479dd1814 | 415 | // |
aktk | 0:86a479dd1814 | 416 | // Format HTTP Response of NACK |
aktk | 0:86a479dd1814 | 417 | // |
aktk | 0:86a479dd1814 | 418 | DEBUG_PRINT_LINE("Communication Protocol won't be Upgraded."); |
aktk | 0:86a479dd1814 | 419 | m_msger.setStatusLine(426, "Upgrade Required"); |
aktk | 0:86a479dd1814 | 420 | if(m_msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger"); |
aktk | 0:86a479dd1814 | 421 | // --- end of formatting --- |
aktk | 0:86a479dd1814 | 422 | } |
aktk | 0:86a479dd1814 | 423 | } |
aktk | 0:86a479dd1814 | 424 | // send valid response |
aktk | 0:86a479dd1814 | 425 | m_msger.sendHTTPResponse(m_tcpcon); |
aktk | 0:86a479dd1814 | 426 | m_msger.resetHeader(); |
aktk | 0:86a479dd1814 | 427 | DEBUG_PRINT_LINE("echo back done."); |
aktk | 0:86a479dd1814 | 428 | } |
aktk | 0:86a479dd1814 | 429 | if (httpmethod == NULL) { |
aktk | 0:86a479dd1814 | 430 | // send error response |
aktk | 0:86a479dd1814 | 431 | m_msger.sendHTTPResponse(m_tcpcon); |
aktk | 0:86a479dd1814 | 432 | m_msger.resetHeader(); |
aktk | 0:86a479dd1814 | 433 | DEBUG_PRINT_LINE("echo back done."); |
aktk | 0:86a479dd1814 | 434 | } |
aktk | 0:86a479dd1814 | 435 | DEBUG_PRINT_LINE("Response to Request has done"); |
aktk | 0:86a479dd1814 | 436 | // ----Handshake Response End---- |
aktk | 0:86a479dd1814 | 437 | |
aktk | 0:86a479dd1814 | 438 | return true; |
aktk | 0:86a479dd1814 | 439 | } |