Port of TI's CC3100 Websock camera demo. Using FreeRTOS, mbedTLS, also parts of Arducam for cams ov5642 and 0v2640. Can also use MT9D111. Work in progress. Be warned some parts maybe a bit flacky. This is for Seeed Arch max only, for an M3, see the demo for CM3 using the 0v5642 aducam mini.
WebSockHandler.cpp
00001 //***************************************************************************** 00002 // Copyright (C) 2014 Texas Instruments Incorporated 00003 // 00004 // All rights reserved. Property of Texas Instruments Incorporated. 00005 // Restricted rights to use, duplicate or disclose this code are 00006 // granted through contract. 00007 // The program may not be used without the written permission of 00008 // Texas Instruments Incorporated or against the terms and conditions 00009 // stipulated in the agreement under which this program has been supplied, 00010 // and under no circumstances can it be used with non-TI connectivity device. 00011 // 00012 //***************************************************************************** 00013 00014 00015 /** 00016 * @addtogroup WebSockHandler 00017 * 00018 * @{ 00019 */ 00020 00021 //#include "HttpHeaders.h" 00022 #include "HttpCore.h" 00023 #include "HttpResponse.h" 00024 #include "HttpRequest.h" 00025 #include "HttpAuth.h" 00026 #include "HttpDebug.h" 00027 #include <string.h> 00028 #include <stdlib.h> 00029 #include "HttpConfig.h" 00030 #include "HttpString.h" 00031 #include "osi.h" 00032 #include "WebSockHandler.h" 00033 #include "httpserverapp.h" 00034 00035 // Include CC3200 SimpleLink headers 00036 #include "cc3100_simplelink.h" 00037 00038 00039 char *GlobRecvBuf; 00040 int64_t GlobPayloadLen; 00041 int64_t GlobRecvLen; 00042 UINT8 RecvMore = 0; 00043 char MaskKey[4]; 00044 UINT8 Mask; 00045 UINT8 Ping = 0; 00046 UINT8 Close = 0; 00047 00048 // WebSocket response status line strings 00049 char WS_STATUS_OK_STR[] = "ok"; 00050 char WS_STATUS_GOING_AWAY_STR[] = "server down"; 00051 char WS_STATUS_ERROR_PROTOCOL_STR[] = "protocol error"; 00052 char WS_STATUS_ERROR_DATATYPE_STR[] = "datatype not supported"; 00053 char WS_STATUS_ERROR_ENCODING_STR[] = "data not interpreted"; 00054 char WS_STATUS_ERROR_OVERFLOW_STR[] = "data too large"; 00055 char WS_STATUS_ERROR_UNEXPECTED_STR[] = "unexpected event server"; 00056 00057 00058 /* This function parses the incoming data packet 00059 * @return 1 if successful 00060 0 if failure 00061 */ 00062 /* 00063 00064 0 1 2 3 00065 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 00066 +-+-+-+-+-------+-+-------------+-------------------------------+ 00067 |F|R|R|R| opcode|M| Payload len | Extended payload length | 00068 |I|S|S|S| (4) |A| (7) | (16/64) | 00069 |N|V|V|V| |S| | (if payload len==126/127) | 00070 | |1|2|3| |K| | | 00071 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + 00072 | Extended payload length continued, if payload len == 127 | 00073 + - - - - - - - - - - - - - - - +-------------------------------+ 00074 | |Masking-key, if MASK set to 1 | 00075 +-------------------------------+-------------------------------+ 00076 | Masking-key (continued) | Payload Data | 00077 +-------------------------------- - - - - - - - - - - - - - - - + 00078 : Payload Data continued ... : 00079 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 00080 | Payload Data continued ... | 00081 +---------------------------------------------------------------+ 00082 00083 00084 */ 00085 00086 int Payloadlength(struct HttpBlob * pData, UINT8 iter) 00087 { 00088 int result = 0x0; 00089 00090 while(iter != 0) 00091 { 00092 result = ((int) (*(pData->pData)) | result); 00093 if(iter != 1) 00094 result = result << 8; 00095 pData->pData += sizeof(UINT8); 00096 pData->uLength -= sizeof(UINT8); 00097 iter--; 00098 } 00099 00100 return result; 00101 } 00102 00103 00104 int WSCore_DataRecv(UINT16 uConnection,struct HttpBlob * pData) 00105 { 00106 UINT8 NextBlock; 00107 int lengthLeft; 00108 UINT16 final,RSV,Opcode; 00109 int PayloadLength; 00110 UINT8 iter; 00111 char *PayloadData; 00112 int RecvLength = (int)pData->uLength; 00113 00114 00115 if(!RecvMore) 00116 { 00117 //Parse the first byte 00118 NextBlock= *(pData->pData); 00119 pData->pData += sizeof(UINT8); 00120 pData->uLength -= sizeof(UINT8); 00121 00122 //Mask bits to get header fields 00123 final = (NextBlock&(0x80)); 00124 RSV = (NextBlock&(0x70)); 00125 Opcode = ((NextBlock&(0x0F))); 00126 00127 //If Final bit is set, this is the last data byte from client - terminating condition 00128 if(final) 00129 HttpDebug("Final datablock received \n\r"); 00130 00131 00132 //Inform user about the opcode 00133 HttpDebug("Opcode is %d\n\r",Opcode); 00134 00135 switch(Opcode) 00136 { 00137 case WS_TEXT: 00138 HttpDebug("Text data\n\r"); 00139 break; 00140 case WS_BINARY: 00141 HttpDebug("Binary data\n\r"); 00142 break; 00143 case WS_CLOSE: 00144 HttpDebug("Client has requested connection to be closed\n\r"); 00145 Close = 1; 00146 WSStatusString(WS_STATUS_OK,pData); 00147 WSCore_DataSend(uConnection,*pData,Opcode); 00148 return 1; 00149 case WS_CONTINUATION: 00150 break; 00151 case WS_PING: 00152 HttpDebug("Ping received\n\r"); 00153 Ping = 1; 00154 break; 00155 case WS_PONG: 00156 HttpDebug("Pong received\n\r"); 00157 break; 00158 default: 00159 HttpDebug("This is unsupported\n\r"); 00160 break; 00161 } 00162 00163 00164 ///If header supports extension, send back error 00165 ///Send error frame : TODO 00166 if(RSV) 00167 HttpDebug("Unsupported extension\n\r"); 00168 00169 //Parse the second byte 00170 NextBlock= *(pData->pData); 00171 pData->pData += sizeof(UINT8); 00172 pData->uLength -= sizeof(UINT8); 00173 00174 Mask = (UINT8)(NextBlock&(0x80)); 00175 PayloadLength = (NextBlock&(0x7F)); 00176 00177 //Payload length cases 00178 // If the payload length is 0x7E, the next 2 bytes represent the length 00179 if(PayloadLength == 0x7E) 00180 { 00181 iter = 2; 00182 PayloadLength = Payloadlength(pData, iter); 00183 } 00184 00185 // If the payload length is 0x7F, the next 8 bytes represent the length 00186 if(PayloadLength == 0x7F) 00187 { 00188 iter = 8; 00189 PayloadLength = Payloadlength(pData, iter); 00190 } 00191 00192 PayloadData = (char *)malloc(PayloadLength); 00193 if(PayloadData == NULL) 00194 { 00195 return 0; 00196 } 00197 memset(PayloadData,'\0',PayloadLength); 00198 GlobRecvBuf = PayloadData; 00199 GlobPayloadLen = PayloadLength; 00200 00201 // If mask bit is set, the 4 bytes after payload length represent the masking key 00202 if(Mask) 00203 { 00204 memcpy(MaskKey,pData->pData,4); 00205 pData->pData += sizeof(UINT32); 00206 pData->uLength -= sizeof(UINT32); 00207 } 00208 00209 int RecvLength = (int)pData->uLength; 00210 00211 //Now, extract payload data 00212 memcpy(GlobRecvBuf,(const char *)(pData->pData),RecvLength); 00213 00214 // Go back and get more data. 00215 if(PayloadLength > RecvLength) 00216 { 00217 GlobRecvLen = RecvLength; // Websocket header has 8 bytes that were also received. 00218 RecvMore = 1; 00219 return 1; 00220 } 00221 } 00222 00223 else 00224 { 00225 memcpy(GlobRecvBuf+GlobRecvLen,(const char *)(pData->pData),RecvLength); 00226 GlobRecvLen += RecvLength; 00227 00228 if(GlobRecvLen < GlobPayloadLen) 00229 return 1; 00230 } 00231 00232 RecvMore = 0; 00233 00234 00235 if(Mask) 00236 { 00237 //UINT8 MaskBlock; 00238 char *pData = GlobRecvBuf; 00239 lengthLeft = GlobPayloadLen; 00240 UINT8 MaskIndex = 0; 00241 while(MaskIndex < 4) 00242 { 00243 NextBlock = (UINT8)(*pData); 00244 NextBlock ^= MaskKey[MaskIndex]; 00245 MaskIndex++; 00246 *pData = NextBlock; 00247 pData += sizeof(UINT8); 00248 lengthLeft -= sizeof(UINT8); 00249 if(lengthLeft == 0) 00250 break; 00251 if(MaskIndex == 4) 00252 MaskIndex = 0; 00253 } 00254 00255 } 00256 00257 *(GlobRecvBuf+GlobPayloadLen) = '\0'; 00258 00259 struct HttpBlob PayLoad; 00260 PayLoad.pData = (UINT8 *)GlobRecvBuf; 00261 PayLoad.uLength = (UINT16)GlobPayloadLen; 00262 00263 if(Ping) 00264 { 00265 HttpDebug("You were Pinged\n\r"); 00266 //You must pong 00267 Opcode = 0x0A; 00268 WSCore_DataSend(uConnection,PayLoad,Opcode); 00269 } 00270 00271 //free(pData->pData); 00272 00273 //Send this data to main 00274 WebSocketRecvEventHandler(uConnection,GlobRecvBuf); 00275 00276 00277 return 1; 00278 00279 } 00280 00281 /*! 00282 * \brief Sends data to a websocket client 00283 * 00284 * \param[in] uConnection Connection number on HTTP server. 00285 * \param[in] PayLoad Structure holding the payload data and the size of the data 00286 * \param[in] Opcode User provides data type (text/binary/ping/pong/close). 00287 * 00288 * \return 1 - If packet was successfully received, parsed and sent to the user API 00289 * 0 - Error 00290 */ 00291 int WSCore_DataSend(UINT16 uConnection, struct HttpBlob PayLoad, UINT8 Opcode) 00292 { 00293 UINT16 usTotalLength; 00294 UINT8 usNextBlock; 00295 UINT16 usPayloadLen; // The heap cannot support beyond 65kb 00296 char *pucPayLoadData = (char *)PayLoad.pData; 00297 00298 usNextBlock = 0; 00299 00300 if(Opcode != 0x02) 00301 usTotalLength = strlen(pucPayLoadData); 00302 else 00303 usTotalLength = PayLoad.uLength; 00304 00305 do{ 00306 wait_ms(10); 00307 ///Is this the final packet? 00308 if(usTotalLength < FRAGMENT_LENGTH) 00309 { 00310 //final = 0x1; 00311 usNextBlock |= 0x80; 00312 } 00313 ///Add opcode to the header 00314 usNextBlock |= Opcode; 00315 00316 /// Add this byte to the sendpacket 00317 HttpResponse_AddCharToResponseHeaders(usNextBlock); 00318 00319 ///Reset byte 00320 usNextBlock = 0x0; 00321 ///Mask bit is always set to 0 from server to client 00322 00323 ///PayloadLen field 00324 if(usTotalLength <= 125) 00325 usPayloadLen = usTotalLength; 00326 else 00327 usPayloadLen = (126); 00328 00329 usNextBlock |= (UINT8)usPayloadLen; 00330 00331 /// Add this byte to the sendpacket 00332 HttpResponse_AddCharToResponseHeaders(usNextBlock); 00333 00334 /// If payload length is more than 125 bytes, we need 16 bits to represent it. 00335 if(usPayloadLen == (126)) 00336 { 00337 00338 if(usTotalLength < FRAGMENT_LENGTH) 00339 usPayloadLen = usTotalLength; 00340 else 00341 usPayloadLen = FRAGMENT_LENGTH; 00342 00343 if(usPayloadLen >= FRAGMENT_LENGTH - 4) 00344 usPayloadLen = FRAGMENT_LENGTH - 4; 00345 00346 usNextBlock = (char)(usPayloadLen>>8); 00347 HttpResponse_AddCharToResponseHeaders(usNextBlock); 00348 usNextBlock = (char)(usPayloadLen); 00349 HttpResponse_AddCharToResponseHeaders(usNextBlock); 00350 } 00351 00352 HttpResponse_AddStringToResponseHeaders(pucPayLoadData,(usPayloadLen)); 00353 wait_ms(2); 00354 if(!WS_SendPacket(uConnection)){ 00355 Uart_Write((uint8_t*)"WS_SendPacket error \n\r"); 00356 return 0; 00357 } 00358 if(Opcode == WS_CLOSE) 00359 { 00360 Uart_Write((uint8_t*)"WS_Close \n\r"); 00361 sl_WebSocketCloseEvtHdlr(); 00362 wait(1); 00363 (HttpCore_CloseConnection(uConnection)); 00364 return 1; 00365 } 00366 00367 usTotalLength -= (usPayloadLen); 00368 // Reset to continuation frame if packet is larger than max fragment size 00369 Opcode = WS_CONTINUATION; 00370 00371 ///Reset byte 00372 usNextBlock = 0x0; 00373 00374 //Update pointer 00375 pucPayLoadData += usPayloadLen; 00376 00377 }while(usTotalLength > 0); 00378 00379 return 1; 00380 } 00381 00382 00383 /** 00384 * Returns status string according to status code - CHANGE 00385 */ 00386 void WSStatusString(UINT32 WS_Status, struct HttpBlob* status) 00387 { 00388 HttpString_utoa(WS_Status, status); 00389 struct HttpBlob blob = {0, NULL}; 00390 switch (WS_Status) 00391 { 00392 case WS_STATUS_OK: 00393 HttpBlobSetConst(blob, WS_STATUS_OK_STR); 00394 break; 00395 case WS_STATUS_GOING_AWAY: 00396 HttpBlobSetConst(blob, WS_STATUS_GOING_AWAY_STR); 00397 break; 00398 case WS_STATUS_ERROR_DATATYPE: 00399 HttpBlobSetConst(blob, WS_STATUS_ERROR_DATATYPE_STR); 00400 break; 00401 case WS_STATUS_ERROR_ENCODING: 00402 HttpBlobSetConst(blob, WS_STATUS_ERROR_ENCODING_STR); 00403 break; 00404 case WS_STATUS_ERROR_OVERFLOW: 00405 HttpBlobSetConst(blob, WS_STATUS_ERROR_OVERFLOW_STR); 00406 break; 00407 case WS_STATUS_ERROR_PROTOCOL: 00408 HttpBlobSetConst(blob, WS_STATUS_ERROR_PROTOCOL_STR); 00409 break; 00410 case WS_STATUS_ERROR_UNEXPECTED: 00411 HttpBlobSetConst(blob, WS_STATUS_ERROR_UNEXPECTED_STR); 00412 break; 00413 default: 00414 HttpDebug("Unknown response status \n\r"); 00415 HttpAssert(0); 00416 break; 00417 } 00418 memcpy(status->pData + status->uLength, blob.pData, blob.uLength); 00419 return; 00420 } 00421 00422 /// @} 00423
Generated on Tue Jul 12 2022 22:22:38 by 1.7.2