TI's CC3100 websocket camera demo with Arducam mini ov5642 and freertos. Should work with other M3's. Work in progress test demo.
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 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 00354 if(!WS_SendPacket(uConnection)) 00355 return 0; 00356 00357 if(Opcode == WS_CLOSE) 00358 { 00359 sl_WebSocketCloseEvtHdlr(); 00360 wait(1); 00361 (HttpCore_CloseConnection(uConnection)); 00362 return 1; 00363 } 00364 00365 usTotalLength -= (usPayloadLen); 00366 00367 // Reset to continuation frame if packet is larger than max fragment size 00368 Opcode = WS_CONTINUATION; 00369 00370 ///Reset byte 00371 usNextBlock = 0x0; 00372 00373 //Update pointer 00374 pucPayLoadData += usPayloadLen; 00375 00376 }while(usTotalLength > 0); 00377 00378 return 1; 00379 } 00380 00381 00382 /** 00383 * Returns status string according to status code - CHANGE 00384 */ 00385 void WSStatusString(UINT32 WS_Status, struct HttpBlob* status) 00386 { 00387 HttpString_utoa(WS_Status, status); 00388 struct HttpBlob blob = {0, NULL}; 00389 switch (WS_Status) 00390 { 00391 case WS_STATUS_OK: 00392 HttpBlobSetConst(blob, WS_STATUS_OK_STR); 00393 break; 00394 case WS_STATUS_GOING_AWAY: 00395 HttpBlobSetConst(blob, WS_STATUS_GOING_AWAY_STR); 00396 break; 00397 case WS_STATUS_ERROR_DATATYPE: 00398 HttpBlobSetConst(blob, WS_STATUS_ERROR_DATATYPE_STR); 00399 break; 00400 case WS_STATUS_ERROR_ENCODING: 00401 HttpBlobSetConst(blob, WS_STATUS_ERROR_ENCODING_STR); 00402 break; 00403 case WS_STATUS_ERROR_OVERFLOW: 00404 HttpBlobSetConst(blob, WS_STATUS_ERROR_OVERFLOW_STR); 00405 break; 00406 case WS_STATUS_ERROR_PROTOCOL: 00407 HttpBlobSetConst(blob, WS_STATUS_ERROR_PROTOCOL_STR); 00408 break; 00409 case WS_STATUS_ERROR_UNEXPECTED: 00410 HttpBlobSetConst(blob, WS_STATUS_ERROR_UNEXPECTED_STR); 00411 break; 00412 default: 00413 HttpDebug("Unknown response status \n\r"); 00414 HttpAssert(0); 00415 break; 00416 } 00417 memcpy(status->pData + status->uLength, blob.pData, blob.uLength); 00418 return; 00419 } 00420 00421 /// @} 00422
Generated on Wed Jul 13 2022 15:58:46 by 1.7.2