WebSocket.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. /*******************************************************************************
  2. * Copyright (c) 2018, 2019 Wind River Systems, Inc. and others. All Rights Reserved.
  3. *
  4. * All rights reserved. This program and the accompanying materials
  5. * are made available under the terms of the Eclipse Public License v1.0
  6. * and Eclipse Distribution License v1.0 which accompany this distribution.
  7. *
  8. * The Eclipse Public License is available at
  9. * http://www.eclipse.org/legal/epl-v10.html
  10. * and the Eclipse Distribution License is available at
  11. * http://www.eclipse.org/org/documents/edl-v10.php.
  12. *
  13. * Contributors:
  14. * Keith Holman - initial implementation and documentation
  15. * Ian Craggs - use memory tracking
  16. *******************************************************************************/
  17. #include <stdint.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "WebSocket.h"
  21. #include "Base64.h"
  22. #include "Log.h"
  23. #include "SHA1.h"
  24. #include "LinkedList.h"
  25. #include "MQTTProtocolOut.h"
  26. #include "SocketBuffer.h"
  27. #include "StackTrace.h"
  28. #if defined(__linux__)
  29. # include <endian.h>
  30. #elif defined(__APPLE__)
  31. # include <libkern/OSByteOrder.h>
  32. # define htobe16(x) OSSwapHostToBigInt16(x)
  33. # define htobe32(x) OSSwapHostToBigInt32(x)
  34. # define htobe64(x) OSSwapHostToBigInt64(x)
  35. # define be16toh(x) OSSwapBigToHostInt16(x)
  36. # define be32toh(x) OSSwapBigToHostInt32(x)
  37. # define be64toh(x) OSSwapBigToHostInt64(x)
  38. #elif defined(__FreeBSD__) || defined(__NetBSD__)
  39. # include <sys/endian.h>
  40. #elif defined(WIN32) || defined(WIN64)
  41. # pragma comment(lib, "rpcrt4.lib")
  42. # include <Rpc.h>
  43. # define strncasecmp(s1,s2,c) _strnicmp(s1,s2,c)
  44. # if BYTE_ORDER == LITTLE_ENDIAN
  45. # define htobe16(x) htons(x)
  46. # define htobe32(x) htonl(x)
  47. # define htobe64(x) htonll(x)
  48. # define be16toh(x) ntohs(x)
  49. # define be32toh(x) ntohl(x)
  50. # define be64toh(x) ntohll(x)
  51. # elif BTYE_ORDER == BIG_ENDIAN
  52. # define htobe16(x) (x)
  53. # define htobe32(x) (x)
  54. # define htobe64(x) (x)
  55. # define be16toh(x) (x)
  56. # define be32toh(x) (x)
  57. # define be64toh(x) (x)
  58. # else
  59. # error "unknown endian"
  60. # endif
  61. /* For Microsoft Visual Studio 2013 */
  62. # if !defined( snprintf )
  63. # define snprintf _snprintf
  64. # endif /* if !defined( snprintf ) */
  65. #endif
  66. #if defined(OPENSSL)
  67. #include "SSLSocket.h"
  68. #endif /* defined(OPENSSL) */
  69. #include "Socket.h"
  70. #if !(defined(WIN32) || defined(WIN64))
  71. #if defined(LIBUUID)
  72. #include <uuid/uuid.h>
  73. #else /* if defined(USE_LIBUUID) */
  74. #include <limits.h>
  75. #include <stdlib.h>
  76. #include <time.h>
  77. #if defined(OPENSSL)
  78. #include <openssl/rand.h>
  79. #endif /* if defined(OPENSSL) */
  80. #include "Heap.h"
  81. /** @brief raw uuid type */
  82. typedef unsigned char uuid_t[16];
  83. /**
  84. * @brief generates a uuid, compatible with RFC 4122, version 4 (random)
  85. * @note Uses a very insecure algorithm but no external dependencies
  86. */
  87. void uuid_generate( uuid_t out )
  88. {
  89. #if defined(OPENSSL)
  90. int rc = RAND_bytes( out, sizeof(uuid_t));
  91. if ( !rc )
  92. #endif /* defined (OPENSSL) */
  93. {
  94. /* very insecure, but generates a random uuid */
  95. int i;
  96. srand(time(NULL));
  97. for ( i = 0; i < 16; ++i )
  98. out[i] = (unsigned char)(rand() % UCHAR_MAX);
  99. out[6] = (out[6] & 0x0f) | 0x40;
  100. out[8] = (out[8] & 0x3F) | 0x80;
  101. }
  102. }
  103. /** @brief converts a uuid to a string */
  104. void uuid_unparse( uuid_t uu, char *out )
  105. {
  106. int i;
  107. for ( i = 0; i < 16; ++i )
  108. {
  109. if ( i == 4 || i == 6 || i == 8 || i == 10 )
  110. {
  111. *out = '-';
  112. ++out;
  113. }
  114. out += sprintf( out, "%02x", uu[i] );
  115. }
  116. *out = '\0';
  117. }
  118. #endif /* else if defined(LIBUUID) */
  119. #endif /* if !(defined(WIN32) || defined(WIN64)) */
  120. /** raw websocket frame data */
  121. struct ws_frame
  122. {
  123. size_t len; /**< length of frame */
  124. size_t pos; /**< current position within the buffer */
  125. };
  126. /** Current frame being processed */
  127. struct ws_frame *last_frame = NULL;
  128. /** Holds any received websocket frames, to be process */
  129. static List* in_frames = NULL;
  130. static char * frame_buffer = NULL;
  131. static size_t frame_buffer_len = 0;
  132. static size_t frame_buffer_index = 0;
  133. static size_t frame_buffer_data_len = 0;
  134. /* static function declarations */
  135. static const char *WebSocket_strcasefind(
  136. const char *buf, const char *str, size_t len);
  137. static char *WebSocket_getRawSocketData(
  138. networkHandles *net, size_t bytes, size_t* actual_len);
  139. static void WebSocket_rewindData( void );
  140. static void WebSocket_pong(
  141. networkHandles *net, char *app_data, size_t app_data_len);
  142. static int WebSocket_receiveFrame(networkHandles *net,
  143. size_t bytes, size_t *actual_len );
  144. /**
  145. * @brief builds a websocket frame for data transmission
  146. *
  147. * write a websocket header and will mask the payload in all the passed in
  148. * buffers
  149. *
  150. * @param[in,out] net network connection
  151. * @param[in] opcode websocket opcode for the packet
  152. * @param[in] mask_data whether to maskt he data
  153. * @param[in,out] buf0 first buffer, will write before this
  154. * @param[in] buf0len size of first buffer
  155. * @param[in] count number of payload buffers
  156. * @param[in,out] buffers array of paylaod buffers
  157. * @param[in] buflens array of payload buffer sizes
  158. * @param[in] freeData array indicating to free payload buffers
  159. *
  160. * @return amount of data to write to socket
  161. */
  162. static int WebSocket_buildFrame(networkHandles* net, int opcode, int mask_data,
  163. char* buf0, size_t buf0len, int count, char** buffers, size_t* buflens)
  164. {
  165. int i;
  166. int buf_len = 0u;
  167. size_t data_len = buf0len;
  168. FUNC_ENTRY;
  169. for (i = 0; i < count; ++i)
  170. data_len += buflens[i];
  171. buf0 -= WebSocket_calculateFrameHeaderSize(net, mask_data, data_len);
  172. if ( net->websocket )
  173. {
  174. uint8_t mask[4];
  175. /* genearate mask, since we are a client */
  176. #if defined(OPENSSL)
  177. RAND_bytes( &mask[0], sizeof(mask) );
  178. #else /* if defined(OPENSSL) */
  179. mask[0] = (rand() % UINT8_MAX);
  180. mask[1] = (rand() % UINT8_MAX);
  181. mask[2] = (rand() % UINT8_MAX);
  182. mask[3] = (rand() % UINT8_MAX);
  183. #endif /* else if defined(OPENSSL) */
  184. /* 1st byte */
  185. buf0[buf_len] = (char)(1 << 7); /* final flag */
  186. /* 3 bits reserved for negotiation of protocol */
  187. buf0[buf_len] |= (char)(opcode & 0x0F); /* op code */
  188. ++buf_len;
  189. /* 2nd byte */
  190. buf0[buf_len] = (char)((mask_data & 0x1) << 7); /* masking bit */
  191. /* payload length */
  192. if ( data_len < 126u )
  193. buf0[buf_len++] |= data_len & 0x7F;
  194. /* 3rd byte & 4th bytes - extended payload length */
  195. else if ( data_len < 65536u )
  196. {
  197. uint16_t len = htobe16((uint16_t)data_len);
  198. buf0[buf_len++] |= (126u & 0x7F);
  199. memcpy( &buf0[buf_len], &len, 2u );
  200. buf_len += 2;
  201. }
  202. else if ( data_len < 0xFFFFFFFFFFFFFFFF )
  203. {
  204. uint64_t len = htobe64((uint64_t)data_len);
  205. buf0[buf_len++] |= (127u & 0x7F);
  206. memcpy( &buf0[buf_len], &len, 8 );
  207. buf_len += 8;
  208. }
  209. else
  210. {
  211. Log(TRACE_PROTOCOL, 1, "Data too large for websocket frame" );
  212. buf_len = -1;
  213. }
  214. /* masking key */
  215. if ( (mask_data & 0x1) && buf_len > 0 )
  216. {
  217. memcpy( &buf0[buf_len], &mask, sizeof(uint32_t));
  218. buf_len += sizeof(uint32_t);
  219. }
  220. /* mask data */
  221. if ( mask_data & 0x1 )
  222. {
  223. size_t idx = 0u;
  224. /* packet fixed header */
  225. for (i = 0; i < (int)buf0len; ++i, ++idx)
  226. buf0[buf_len + i] ^= mask[idx % 4];
  227. /* variable data buffers */
  228. for (i = 0; i < count; ++i)
  229. {
  230. size_t j;
  231. for ( j = 0u; j < buflens[i]; ++j, ++idx )
  232. buffers[i][j] ^= mask[idx % 4];
  233. }
  234. }
  235. }
  236. FUNC_EXIT_RC(buf_len);
  237. return buf_len;
  238. }
  239. /**
  240. * calculates the amount of data required for the websocket header
  241. *
  242. * this function is used to calculate how much offset is required before calling
  243. * @p WebSocket_putdatas, as that function will write data before the passed in
  244. * buffer
  245. *
  246. * @param[in,out] net network connection
  247. * @param[in] mask_data whether to mask the data
  248. * @param[in] data_len amount of data in the payload
  249. *
  250. * @return the size in bytes of the websocket header required
  251. *
  252. * @see WebSocket_putdatas
  253. */
  254. size_t WebSocket_calculateFrameHeaderSize(networkHandles *net, int mask_data,
  255. size_t data_len)
  256. {
  257. int ret = 0;
  258. if ( net && net->websocket )
  259. {
  260. if ( data_len < 126u)
  261. ret = 2; /* header 2 bytes */
  262. else if ( data_len < 65536u )
  263. ret = 4; /* for extra 2-bytes for payload length */
  264. else if ( data_len < 0xFFFFFFFFFFFFFFFF )
  265. ret = 10; /* for extra 8-bytes for payload length */
  266. if ( mask_data & 0x1 )
  267. ret += sizeof(uint32_t); /* for mask */
  268. }
  269. return ret;
  270. }
  271. /**
  272. * sends out a websocket request on the given uri
  273. *
  274. * @param[in] net network connection
  275. * @param[in] uri uri to connect to
  276. *
  277. * @retval SOCKET_ERROR on failure
  278. * @retval 1 on success
  279. *
  280. * @see WebSocket_upgrade
  281. */
  282. int WebSocket_connect( networkHandles *net, const char *uri )
  283. {
  284. int rc;
  285. char *buf = NULL;
  286. int i, buf_len = 0;
  287. size_t hostname_len;
  288. int port = 80;
  289. const char *topic = NULL;
  290. #if defined(WIN32) || defined(WIN64)
  291. UUID uuid;
  292. #else /* if defined(WIN32) || defined(WIN64) */
  293. uuid_t uuid;
  294. #endif /* else if defined(WIN32) || defined(WIN64) */
  295. FUNC_ENTRY;
  296. /* Generate UUID */
  297. if (net->websocket_key == NULL)
  298. net->websocket_key = malloc(25u);
  299. else
  300. net->websocket_key = realloc(net->websocket_key, 25u);
  301. #if defined(WIN32) || defined(WIN64)
  302. ZeroMemory( &uuid, sizeof(UUID) );
  303. UuidCreate( &uuid );
  304. Base64_encode( net->websocket_key, 25u, (const b64_data_t*)&uuid, sizeof(UUID) );
  305. #else /* if defined(WIN32) || defined(WIN64) */
  306. uuid_generate( uuid );
  307. Base64_encode( net->websocket_key, 25u, uuid, sizeof(uuid_t) );
  308. #endif /* else if defined(WIN32) || defined(WIN64) */
  309. hostname_len = MQTTProtocol_addressPort(uri, &port, &topic);
  310. /* if no topic, use default */
  311. if ( !topic )
  312. topic = "/mqtt";
  313. for ( i = 0; i < 2; ++i )
  314. {
  315. buf_len = snprintf( buf, (size_t)buf_len,
  316. "GET %s HTTP/1.1\r\n"
  317. "Host: %.*s:%d\r\n"
  318. "Upgrade: websocket\r\n"
  319. "Connection: Upgrade\r\n"
  320. "Origin: http://%.*s:%d\r\n"
  321. "Sec-WebSocket-Key: %s\r\n"
  322. "Sec-WebSocket-Version: 13\r\n"
  323. "Sec-WebSocket-Protocol: mqtt\r\n"
  324. "\r\n", topic,
  325. (int)hostname_len, uri, port,
  326. (int)hostname_len, uri, port,
  327. net->websocket_key );
  328. if ( i == 0 && buf_len > 0 )
  329. {
  330. ++buf_len; /* need 1 extra byte for ending '\0' */
  331. buf = malloc( buf_len );
  332. }
  333. }
  334. if ( buf )
  335. {
  336. #if defined(OPENSSL)
  337. if (net->ssl)
  338. SSLSocket_putdatas(net->ssl, net->socket,
  339. buf, buf_len, 0, NULL, NULL, NULL );
  340. else
  341. #endif
  342. Socket_putdatas( net->socket, buf, buf_len,
  343. 0, NULL, NULL, NULL );
  344. free( buf );
  345. rc = 1;
  346. }
  347. else
  348. {
  349. free(net->websocket_key);
  350. net->websocket_key = NULL;
  351. rc = SOCKET_ERROR;
  352. }
  353. FUNC_EXIT_RC(rc);
  354. return rc;
  355. }
  356. /**
  357. * closes a websocket connection
  358. *
  359. * @param[in,out] net structure containing network connection
  360. * @param[in] status_code websocket close status code
  361. * @param[in] reason reason for closing connection (optional)
  362. */
  363. void WebSocket_close(networkHandles *net, int status_code, const char *reason)
  364. {
  365. FUNC_ENTRY;
  366. if ( net->websocket )
  367. {
  368. char *buf0;
  369. size_t buf0len = sizeof(uint16_t);
  370. size_t header_len;
  371. uint16_t status_code_be;
  372. const int mask_data = 0;
  373. if ( status_code < WebSocket_CLOSE_NORMAL ||
  374. status_code > WebSocket_CLOSE_TLS_FAIL )
  375. status_code = WebSocket_CLOSE_GOING_AWAY;
  376. if ( reason )
  377. buf0len += strlen(reason);
  378. header_len = WebSocket_calculateFrameHeaderSize(net,
  379. mask_data, buf0len);
  380. buf0 = malloc(header_len + buf0len);
  381. if ( !buf0 ) return;
  382. /* encode status code */
  383. status_code_be = htobe16((uint16_t)status_code);
  384. memcpy( &buf0[header_len], &status_code_be, sizeof(uint16_t));
  385. /* encode reason, if provided */
  386. if ( reason )
  387. strcpy( &buf0[header_len + sizeof(uint16_t)], reason );
  388. WebSocket_buildFrame( net, WebSocket_OP_CLOSE, mask_data,
  389. &buf0[header_len], buf0len, 0, NULL, NULL );
  390. buf0len += header_len;
  391. #if defined(OPENSSL)
  392. if (net->ssl)
  393. SSLSocket_putdatas(net->ssl, net->socket,
  394. buf0, buf0len, 0, NULL, NULL, NULL);
  395. else
  396. #endif
  397. Socket_putdatas(net->socket, buf0, buf0len, 0,
  398. NULL, NULL, NULL);
  399. /* websocket connection is now closed */
  400. net->websocket = 0;
  401. free( buf0 );
  402. }
  403. if ( net->websocket_key )
  404. {
  405. free( net->websocket_key );
  406. net->websocket_key = NULL;
  407. }
  408. FUNC_EXIT;
  409. }
  410. /**
  411. * @brief receives 1 byte from a socket
  412. *
  413. * @param[in,out] net network connection
  414. * @param[out] c byte that was read
  415. *
  416. * @retval SOCKET_ERROR on error
  417. * @retval TCPSOCKET_INTERRUPTED no data available
  418. * @retval TCPSOCKET_COMPLETE on success
  419. *
  420. * @see WebSocket_getdata
  421. */
  422. int WebSocket_getch(networkHandles *net, char* c)
  423. {
  424. int rc = SOCKET_ERROR;
  425. FUNC_ENTRY;
  426. if ( net->websocket )
  427. {
  428. struct ws_frame *frame = NULL;
  429. if ( in_frames && in_frames->first )
  430. frame = in_frames->first->content;
  431. if ( !frame )
  432. {
  433. size_t actual_len = 0u;
  434. rc = WebSocket_receiveFrame( net, 1u, &actual_len );
  435. if ( rc != TCPSOCKET_COMPLETE )
  436. goto exit;
  437. /* we got a frame, let take off the top of queue */
  438. if ( in_frames->first )
  439. frame = in_frames->first->content;
  440. }
  441. /* set current working frame */
  442. if (frame && frame->len > frame->pos)
  443. {
  444. unsigned char *buf =
  445. (unsigned char *)frame + sizeof(struct ws_frame);
  446. *c = buf[frame->pos++];
  447. rc = TCPSOCKET_COMPLETE;
  448. }
  449. }
  450. #if defined(OPENSSL)
  451. else if ( net->ssl )
  452. rc = SSLSocket_getch(net->ssl, net->socket, c);
  453. #endif
  454. else
  455. rc = Socket_getch(net->socket, c);
  456. exit:
  457. FUNC_EXIT_RC(rc);
  458. return rc;
  459. }
  460. /**
  461. * @brief receives data from a socket
  462. *
  463. * @param[in,out] net network connection
  464. * @param[in] bytes amount of data to get (0 if last packet)
  465. * @param[out] actual_len amount of data read
  466. *
  467. * @return a pointer to the read data
  468. *
  469. * @see WebSocket_getch
  470. */
  471. char *WebSocket_getdata(networkHandles *net, size_t bytes, size_t* actual_len)
  472. {
  473. char *rv = NULL;
  474. int rc = 0;
  475. FUNC_ENTRY;
  476. if ( net->websocket )
  477. {
  478. struct ws_frame *frame = NULL;
  479. if ( bytes == 0u )
  480. {
  481. /* done with current frame, move it to last frame */
  482. if ( in_frames && in_frames->first )
  483. frame = in_frames->first->content;
  484. /* return the data from the next frame, if we have one */
  485. if ( frame )
  486. {
  487. rv = (char *)frame +
  488. sizeof(struct ws_frame) + frame->pos;
  489. *actual_len = frame->len - frame->pos;
  490. if ( last_frame )
  491. free( last_frame );
  492. last_frame = ListDetachHead(in_frames);
  493. }
  494. goto exit;
  495. }
  496. /* no current frame, let's see if there's one in the list */
  497. if ( in_frames && in_frames->first )
  498. frame = in_frames->first->content;
  499. /* no current frame, so let's go receive one for the network */
  500. if ( !frame )
  501. {
  502. const int rc =
  503. WebSocket_receiveFrame( net, bytes, actual_len );
  504. if ( rc == TCPSOCKET_COMPLETE && in_frames && in_frames->first)
  505. frame = in_frames->first->content;
  506. }
  507. if ( frame )
  508. {
  509. rv = (char *)frame + sizeof(struct ws_frame) + frame->pos;
  510. *actual_len = frame->len - frame->pos;
  511. if ( *actual_len == bytes && in_frames)
  512. {
  513. /* set new frame as current frame */
  514. if ( last_frame )
  515. free( last_frame );
  516. last_frame = ListDetachHead(in_frames);
  517. }
  518. }
  519. }
  520. #if defined(OPENSSL)
  521. else if ( net->ssl )
  522. rv = SSLSocket_getdata(net->ssl, net->socket, bytes, actual_len);
  523. #endif
  524. else
  525. rv = Socket_getdata(net->socket, bytes, actual_len);
  526. exit:
  527. rc = rv != NULL;
  528. FUNC_EXIT_RC(rc);
  529. return rv;
  530. }
  531. void WebSocket_rewindData( void )
  532. {
  533. frame_buffer_index = 0;
  534. }
  535. /**
  536. * reads raw socket data for underlying layers
  537. *
  538. * @param[in] net network connection
  539. * @param[in] bytes number of bytes to read, 0 to complete packet
  540. * @param[in] actual_len amount of data read
  541. *
  542. * @return a buffer containing raw data
  543. */
  544. char *WebSocket_getRawSocketData(
  545. networkHandles *net, size_t bytes, size_t* actual_len)
  546. {
  547. char *rv;
  548. if (bytes > 0)
  549. {
  550. if (frame_buffer_data_len - frame_buffer_index >= bytes)
  551. {
  552. *actual_len = bytes;
  553. rv = frame_buffer + frame_buffer_index;
  554. frame_buffer_index += bytes;
  555. goto exit;
  556. }
  557. else
  558. {
  559. bytes = bytes - (frame_buffer_data_len - frame_buffer_index);
  560. }
  561. }
  562. *actual_len = 0;
  563. // not enough data in the buffer, get data from socket
  564. #if defined(OPENSSL)
  565. if ( net->ssl )
  566. rv = SSLSocket_getdata(net->ssl, net->socket, bytes, actual_len);
  567. else
  568. #endif
  569. rv = Socket_getdata(net->socket, bytes, actual_len);
  570. // clear buffer
  571. if (bytes == 0)
  572. {
  573. frame_buffer_index = 0;
  574. frame_buffer_data_len = 0;
  575. frame_buffer_len = 0;
  576. free (frame_buffer);
  577. frame_buffer = NULL;
  578. }
  579. // append data to the buffer
  580. else if (rv != NULL)
  581. {
  582. // no buffer allocated
  583. if (!frame_buffer)
  584. {
  585. frame_buffer = (char *)malloc(*actual_len);
  586. memcpy(frame_buffer, rv, *actual_len);
  587. frame_buffer_index = 0;
  588. frame_buffer_data_len = *actual_len;
  589. frame_buffer_len = *actual_len;
  590. }
  591. // buffer size is big enough
  592. else if (frame_buffer_data_len + *actual_len < frame_buffer_len)
  593. {
  594. memcpy(frame_buffer + frame_buffer_data_len, rv, *actual_len);
  595. frame_buffer_data_len += *actual_len;
  596. }
  597. // resize buffer
  598. else
  599. {
  600. frame_buffer = realloc(frame_buffer, frame_buffer_data_len + *actual_len);
  601. frame_buffer_len = frame_buffer_data_len + *actual_len;
  602. memcpy(frame_buffer + frame_buffer_data_len, rv, *actual_len);
  603. frame_buffer_data_len += *actual_len;
  604. }
  605. SocketBuffer_complete(net->socket);
  606. }
  607. else
  608. {
  609. return rv;
  610. }
  611. // if possible, return data from the buffer
  612. if (bytes > 0)
  613. {
  614. if (frame_buffer_data_len - frame_buffer_index >= bytes)
  615. {
  616. *actual_len = bytes;
  617. rv = frame_buffer + frame_buffer_index;
  618. frame_buffer_index += bytes;
  619. }
  620. else
  621. {
  622. *actual_len = frame_buffer_data_len - frame_buffer_index;
  623. rv = frame_buffer + frame_buffer_index;
  624. frame_buffer_index += *actual_len;
  625. }
  626. }
  627. exit:
  628. return rv;
  629. }
  630. /**
  631. * sends a "websocket pong" message
  632. *
  633. * @param[in] net network connection
  634. * @param[in] app_data application data to put in payload
  635. * @param[in] app_data_len application data length
  636. */
  637. void WebSocket_pong(networkHandles *net, char *app_data,
  638. size_t app_data_len)
  639. {
  640. FUNC_ENTRY;
  641. if ( net->websocket )
  642. {
  643. char *buf0;
  644. size_t header_len;
  645. int freeData = 0;
  646. const int mask_data = 0;
  647. header_len = WebSocket_calculateFrameHeaderSize(net, mask_data,
  648. app_data_len);
  649. buf0 = malloc(header_len);
  650. if ( !buf0 ) return;
  651. WebSocket_buildFrame( net, WebSocket_OP_PONG, 1,
  652. &buf0[header_len], header_len, mask_data, &app_data,
  653. &app_data_len );
  654. Log(TRACE_PROTOCOL, 1, "Sending WebSocket PONG" );
  655. #if defined(OPENSSL)
  656. if (net->ssl)
  657. SSLSocket_putdatas(net->ssl, net->socket, buf0,
  658. header_len + app_data_len, 1,
  659. &app_data, &app_data_len, &freeData);
  660. else
  661. #endif
  662. Socket_putdatas(net->socket, buf0,
  663. header_len + app_data_len, 1,
  664. &app_data, &app_data_len, &freeData );
  665. /* clean up memory */
  666. free( buf0 );
  667. }
  668. FUNC_EXIT;
  669. }
  670. /**
  671. * writes data to a socket (websocket header will be prepended if required)
  672. *
  673. * @warning buf0 will be expanded (backwords before @p buf0 buffer, to add a
  674. * websocket frame header to the data if required). So use
  675. * @p WebSocket_calculateFrameHeader, to determine if extra space is needed
  676. * before the @p buf0 pointer.
  677. *
  678. * @param[in,out] net network connection
  679. * @param[in,out] buf0 first buffer
  680. * @param[in] buf0len size of first buffer
  681. * @param[in] count number of payload buffers
  682. * @param[in,out] buffers array of paylaod buffers
  683. * @param[in] buflens array of payload buffer sizes
  684. * @param[in] freeData array indicating to free payload buffers
  685. *
  686. * @return amount of data wrote to socket
  687. *
  688. * @see WebSocket_calculateFrameHeaderSize
  689. */
  690. int WebSocket_putdatas(networkHandles* net, char* buf0, size_t buf0len,
  691. int count, char** buffers, size_t* buflens, int* freeData)
  692. {
  693. int rc;
  694. FUNC_ENTRY;
  695. /* prepend WebSocket frame */
  696. if ( net->websocket )
  697. {
  698. size_t data_len = buf0len + 4u;
  699. size_t header_len;
  700. const int mask_data = 1;
  701. for (rc = 0; rc < count; ++rc)
  702. data_len += buflens[rc];
  703. header_len = WebSocket_calculateFrameHeaderSize(
  704. net, mask_data, data_len);
  705. rc = WebSocket_buildFrame(
  706. net, WebSocket_OP_BINARY, mask_data, buf0, buf0len,
  707. count, buffers, buflens );
  708. /* header added so adjust buffer */
  709. if ( rc > 0 )
  710. {
  711. buf0 -= header_len;
  712. buf0len += header_len;
  713. }
  714. }
  715. #if defined(OPENSSL)
  716. if (net->ssl)
  717. rc = SSLSocket_putdatas(net->ssl, net->socket, buf0, buf0len, count, buffers, buflens, freeData);
  718. else
  719. #endif
  720. rc = Socket_putdatas(net->socket, buf0, buf0len, count, buffers, buflens, freeData);
  721. FUNC_EXIT_RC(rc);
  722. return rc;
  723. }
  724. /**
  725. * receives incoming socket data and parses websocket frames
  726. *
  727. * @param[in] net network connection
  728. * @param[in] bytes amount of data to receive
  729. * @param[out] actual_len amount of data actually read
  730. *
  731. * @retval TCPSOCKET_COMPLETE packet received
  732. * @retval TCPSOCKET_INTERRUPTED incomplete packet received
  733. * @retval SOCKET_ERROR an error was encountered
  734. */
  735. int WebSocket_receiveFrame(networkHandles *net,
  736. size_t bytes, size_t *actual_len )
  737. {
  738. struct ws_frame *res = NULL;
  739. int rc = TCPSOCKET_COMPLETE;
  740. FUNC_ENTRY;
  741. if ( !in_frames )
  742. in_frames = ListInitialize();
  743. /* see if there is frame acurrently on queue */
  744. if ( in_frames->first )
  745. res = in_frames->first->content;
  746. while( !res )
  747. {
  748. int opcode = WebSocket_OP_BINARY;
  749. do
  750. {
  751. /* obtain all frames in the sequence */
  752. int final = 0;
  753. while ( !final )
  754. {
  755. char *b;
  756. size_t len = 0u;
  757. int tmp_opcode;
  758. int has_mask;
  759. size_t cur_len = 0u;
  760. uint8_t mask[4] = { 0u, 0u, 0u, 0u };
  761. size_t payload_len;
  762. b = WebSocket_getRawSocketData(net, 2u, &len);
  763. if ( !b )
  764. {
  765. rc = SOCKET_ERROR;
  766. goto exit;
  767. }
  768. else if (len < 2u )
  769. {
  770. rc = TCPSOCKET_INTERRUPTED;
  771. goto exit;
  772. }
  773. /* 1st byte */
  774. final = (b[0] & 0xFF) >> 7;
  775. tmp_opcode = (b[0] & 0x0F);
  776. if ( tmp_opcode ) /* not a continuation frame */
  777. opcode = tmp_opcode;
  778. /* invalid websocket packet must return error */
  779. if ( opcode < WebSocket_OP_CONTINUE ||
  780. opcode > WebSocket_OP_PONG ||
  781. ( opcode > WebSocket_OP_BINARY &&
  782. opcode < WebSocket_OP_CLOSE ) )
  783. {
  784. rc = SOCKET_ERROR;
  785. goto exit;
  786. }
  787. /* 2nd byte */
  788. has_mask = (b[1] & 0xFF) >> 7;
  789. payload_len = (b[1] & 0x7F);
  790. /* determine payload length */
  791. if ( payload_len == 126 )
  792. {
  793. b = WebSocket_getRawSocketData( net,
  794. 2u, &len);
  795. if ( !b )
  796. {
  797. rc = SOCKET_ERROR;
  798. goto exit;
  799. }
  800. else if (len < 2u )
  801. {
  802. rc = TCPSOCKET_INTERRUPTED;
  803. goto exit;
  804. }
  805. /* convert from big endian 16 to host */
  806. payload_len = be16toh(*(uint16_t*)b);
  807. }
  808. else if ( payload_len == 127 )
  809. {
  810. b = WebSocket_getRawSocketData( net,
  811. 8u, &len);
  812. if ( !b )
  813. {
  814. rc = SOCKET_ERROR;
  815. goto exit;
  816. }
  817. else if (len < 8u )
  818. {
  819. rc = TCPSOCKET_INTERRUPTED;
  820. goto exit;
  821. }
  822. /* convert from big-endian 64 to host */
  823. payload_len = (size_t)be64toh(*(uint64_t*)b);
  824. }
  825. if ( has_mask )
  826. {
  827. uint8_t mask[4];
  828. b = WebSocket_getRawSocketData(net, 4u, &len);
  829. if ( !b )
  830. {
  831. rc = SOCKET_ERROR;
  832. goto exit;
  833. }
  834. else if (len < 4u )
  835. {
  836. rc = TCPSOCKET_INTERRUPTED;
  837. goto exit;
  838. }
  839. memcpy( &mask[0], b, sizeof(uint32_t));
  840. }
  841. b = WebSocket_getRawSocketData(net,
  842. payload_len, &len);
  843. if ( !b )
  844. {
  845. rc = SOCKET_ERROR;
  846. goto exit;
  847. }
  848. else if (len < payload_len )
  849. {
  850. rc = TCPSOCKET_INTERRUPTED;
  851. goto exit;
  852. }
  853. /* unmask data */
  854. if ( has_mask )
  855. {
  856. size_t i;
  857. for ( i = 0u; i < payload_len; ++i )
  858. b[i] ^= mask[i % 4];
  859. }
  860. if ( res )
  861. cur_len = res->len;
  862. if (res == NULL)
  863. res = malloc( sizeof(struct ws_frame) + cur_len + len );
  864. else
  865. res = realloc( res, sizeof(struct ws_frame) + cur_len + len );
  866. memcpy( (unsigned char *)res + sizeof(struct ws_frame) + cur_len, b, len );
  867. res->pos = 0u;
  868. res->len = cur_len + len;
  869. WebSocket_getRawSocketData(net, 0u, &len);
  870. }
  871. if ( opcode == WebSocket_OP_PING || opcode == WebSocket_OP_PONG )
  872. {
  873. /* respond to a "ping" with a "pong" */
  874. if ( opcode == WebSocket_OP_PING )
  875. WebSocket_pong( net,
  876. (char *)res + sizeof(struct ws_frame),
  877. res->len );
  878. /* discard message */
  879. free( res );
  880. res = NULL;
  881. }
  882. else if ( opcode == WebSocket_OP_CLOSE )
  883. {
  884. /* server end closed websocket connection */
  885. free( res );
  886. WebSocket_close( net, WebSocket_CLOSE_GOING_AWAY, NULL );
  887. rc = SOCKET_ERROR; /* closes socket */
  888. goto exit;
  889. }
  890. } while ( opcode == WebSocket_OP_PING || opcode == WebSocket_OP_PONG );
  891. }
  892. /* add new frame to end of list */
  893. ListAppend( in_frames, res, sizeof(struct ws_frame) + res->len);
  894. *actual_len = res->len - res->pos;
  895. exit:
  896. if (rc == TCPSOCKET_INTERRUPTED)
  897. {
  898. WebSocket_rewindData();
  899. }
  900. FUNC_EXIT_RC(rc);
  901. return rc;
  902. }
  903. /**
  904. * case-insensitive string search
  905. *
  906. * similar to @p strcase, but takes a maximum length
  907. *
  908. * @param[in] buf buffer to search
  909. * @param[in] str string to find
  910. * @param[in] len length of the buffer
  911. *
  912. * @retval !NULL location of string found
  913. * @retval NULL string not found
  914. */
  915. const char *WebSocket_strcasefind(const char *buf, const char *str, size_t len)
  916. {
  917. const char *res = NULL;
  918. if ( buf && len > 0u && str )
  919. {
  920. const size_t str_len = strlen( str );
  921. while ( len >= str_len && !res )
  922. {
  923. if ( strncasecmp( buf, str, str_len ) == 0 )
  924. res = buf;
  925. ++buf;
  926. --len;
  927. }
  928. }
  929. return res;
  930. }
  931. /**
  932. * releases resources used by the websocket sub-system
  933. */
  934. void WebSocket_terminate( void )
  935. {
  936. FUNC_ENTRY;
  937. /* clean up and un-processed websocket frames */
  938. if ( in_frames )
  939. {
  940. struct ws_frame *f = ListDetachHead( in_frames );
  941. while ( f )
  942. {
  943. free( f );
  944. f = ListDetachHead( in_frames );
  945. }
  946. ListFree( in_frames );
  947. in_frames = NULL;
  948. }
  949. if ( last_frame )
  950. {
  951. free( last_frame );
  952. last_frame = NULL;
  953. }
  954. if ( frame_buffer )
  955. {
  956. free( frame_buffer );
  957. frame_buffer = NULL;
  958. }
  959. frame_buffer_len = 0;
  960. frame_buffer_index = 0;
  961. frame_buffer_data_len = 0;
  962. Socket_outTerminate();
  963. #if defined(OPENSSL)
  964. SSLSocket_terminate();
  965. #endif
  966. FUNC_EXIT;
  967. }
  968. /**
  969. * handles the websocket upgrade response
  970. *
  971. * @param[in,out] net network connection to upgrade
  972. *
  973. * @retval SOCKET_ERROR failed to upgrade network connection
  974. * @retval 1 socket upgraded to use websockets
  975. *
  976. * @see WebSocket_connect
  977. */
  978. int WebSocket_upgrade( networkHandles *net )
  979. {
  980. static const char *const ws_guid =
  981. "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
  982. int rc = SOCKET_ERROR;
  983. FUNC_ENTRY;
  984. if ( net->websocket_key )
  985. {
  986. SHA_CTX ctx;
  987. char ws_key[62u] = { 0 };
  988. unsigned char sha_hash[SHA1_DIGEST_LENGTH];
  989. size_t rcv = 0u;
  990. char *read_buf;
  991. /* calculate the expected websocket key, expected from server */
  992. snprintf( ws_key, sizeof(ws_key), "%s%s", net->websocket_key, ws_guid );
  993. SHA1_Init( &ctx );
  994. SHA1_Update( &ctx, ws_key, strlen(ws_key));
  995. SHA1_Final( sha_hash, &ctx );
  996. Base64_encode( ws_key, sizeof(ws_key), sha_hash, SHA1_DIGEST_LENGTH );
  997. rc = TCPSOCKET_INTERRUPTED;
  998. read_buf = WebSocket_getRawSocketData( net, 12u, &rcv );
  999. if ( rcv > 0 && strncmp( read_buf, "HTTP/1.1", 8u ) == 0 )
  1000. {
  1001. if (strncmp( &read_buf[9], "101", 3u ) != 0)
  1002. {
  1003. Log(TRACE_PROTOCOL, 1, "WebSocket HTTP rc %.3s", &read_buf[9]);
  1004. rc = SOCKET_ERROR;
  1005. goto exit;
  1006. }
  1007. }
  1008. if ( rcv > 0 && strncmp( read_buf, "HTTP/1.1 101", 12u ) == 0 )
  1009. {
  1010. const char *p;
  1011. read_buf = WebSocket_getRawSocketData( net, 500u, &rcv );
  1012. /* check for upgrade */
  1013. p = WebSocket_strcasefind(
  1014. read_buf, "Connection", rcv );
  1015. if ( p )
  1016. {
  1017. const char *eol;
  1018. eol = memchr( p, '\n', rcv-(read_buf-p) );
  1019. if ( eol )
  1020. p = WebSocket_strcasefind(
  1021. p, "Upgrade", eol - p);
  1022. else
  1023. p = NULL;
  1024. }
  1025. /* check key hash */
  1026. if ( p )
  1027. p = WebSocket_strcasefind( read_buf,
  1028. "sec-websocket-accept", rcv );
  1029. if ( p )
  1030. {
  1031. const char *eol;
  1032. eol = memchr( p, '\n', rcv-(read_buf-p) );
  1033. if ( eol )
  1034. {
  1035. p = memchr( p, ':', eol-p );
  1036. if ( p )
  1037. {
  1038. size_t hash_len = eol-p-1;
  1039. while ( *p == ':' || *p == ' ' )
  1040. {
  1041. ++p;
  1042. --hash_len;
  1043. }
  1044. if ( strncmp( p, ws_key, hash_len ) != 0 )
  1045. p = NULL;
  1046. }
  1047. }
  1048. else
  1049. p = NULL;
  1050. }
  1051. if ( p )
  1052. {
  1053. net->websocket = 1;
  1054. Log(TRACE_PROTOCOL, 1, "WebSocket connection upgraded" );
  1055. rc = 1;
  1056. }
  1057. else
  1058. {
  1059. Log(TRACE_PROTOCOL, 1, "WebSocket failed to upgrade connection" );
  1060. rc = SOCKET_ERROR;
  1061. }
  1062. if ( net->websocket_key )
  1063. {
  1064. free(net->websocket_key);
  1065. net->websocket_key = NULL;
  1066. }
  1067. /* indicate that we done with the packet */
  1068. WebSocket_getRawSocketData( net, 0u, &rcv );
  1069. }
  1070. }
  1071. exit:
  1072. FUNC_EXIT_RC(rc);
  1073. return rc;
  1074. }