Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

696 рядки
24 KiB

  1. #ifdef _WIN32
  2. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
  3. #define _CRT_SECURE_NO_WARNINGS // _CRT_SECURE_NO_WARNINGS for sscanf errors in MSVC2013 Express
  4. #endif
  5. #ifndef WIN32_LEAN_AND_MEAN
  6. #define WIN32_LEAN_AND_MEAN
  7. #endif
  8. #include <fcntl.h>
  9. #include <WinSock2.h>
  10. #include <WS2tcpip.h>
  11. #pragma comment(lib, "ws2_32")
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <sys/types.h>
  16. #include <io.h>
  17. #ifndef _SSIZE_T_DEFINED
  18. typedef int ssize_t;
  19. #define _SSIZE_T_DEFINED
  20. #endif
  21. #ifndef _SOCKET_T_DEFINED
  22. typedef SOCKET socket_t;
  23. #define _SOCKET_T_DEFINED
  24. #endif
  25. #ifndef snprintf
  26. #define snprintf _snprintf_s
  27. #endif
  28. #if _MSC_VER >= 1600
  29. // vs2010 or later
  30. #include <stdint.h>
  31. #else
  32. typedef __int8 int8_t;
  33. typedef unsigned __int8 uint8_t;
  34. typedef __int32 int32_t;
  35. typedef unsigned __int32 uint32_t;
  36. typedef __int64 int64_t;
  37. typedef unsigned __int64 uint64_t;
  38. #endif
  39. #define socketerrno WSAGetLastError()
  40. #define SOCKET_EAGAIN_EINPROGRESS WSAEINPROGRESS
  41. #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
  42. #else
  43. #include <fcntl.h>
  44. #include <netdb.h>
  45. #include <netinet/in.h>
  46. #include <netinet/tcp.h>
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <sys/socket.h>
  51. #include <sys/time.h>
  52. #include <sys/types.h>
  53. #include <unistd.h>
  54. #include <stdint.h>
  55. #ifndef _SOCKET_T_DEFINED
  56. typedef int socket_t;
  57. #define _SOCKET_T_DEFINED
  58. #endif
  59. #ifndef INVALID_SOCKET
  60. #define INVALID_SOCKET (-1)
  61. #endif
  62. #ifndef SOCKET_ERROR
  63. #define SOCKET_ERROR (-1)
  64. #endif
  65. #define closesocket(s) ::close(s)
  66. #include <errno.h>
  67. #define socketerrno errno
  68. #define SOCKET_EAGAIN_EINPROGRESS EAGAIN
  69. #define SOCKET_EWOULDBLOCK EWOULDBLOCK
  70. #endif
  71. #include <vector>
  72. #include <string>
  73. #include "easywsclient.hpp"
  74. using easywsclient::BytesCallback_Imp;
  75. using easywsclient::Callback_Imp;
  76. namespace
  77. { // private module-only namespace
  78. socket_t hostname_connect(const std::string &hostname, int port)
  79. {
  80. struct addrinfo hints;
  81. struct addrinfo *result;
  82. struct addrinfo *p;
  83. int ret;
  84. socket_t sockfd = INVALID_SOCKET;
  85. char sport[16];
  86. memset(&hints, 0, sizeof(hints));
  87. hints.ai_family = AF_UNSPEC;
  88. hints.ai_socktype = SOCK_STREAM;
  89. snprintf(sport, 16, "%d", port);
  90. if ((ret = getaddrinfo(hostname.c_str(), sport, &hints, &result)) != 0)
  91. {
  92. fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
  93. return 1;
  94. }
  95. for (p = result; p != NULL; p = p->ai_next)
  96. {
  97. sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
  98. if (sockfd == INVALID_SOCKET)
  99. {
  100. continue;
  101. }
  102. if (connect(sockfd, p->ai_addr, p->ai_addrlen) != SOCKET_ERROR)
  103. {
  104. break;
  105. }
  106. closesocket(sockfd);
  107. sockfd = INVALID_SOCKET;
  108. }
  109. freeaddrinfo(result);
  110. return sockfd;
  111. }
  112. class _DummyWebSocket : public easywsclient::WebSocket
  113. {
  114. public:
  115. void poll(int timeout) {}
  116. void send(const std::string &message) {}
  117. void sendBinary(const std::string &message) {}
  118. void sendBinary(const std::vector<uint8_t> &message) {}
  119. void sendPing() {}
  120. void close() {}
  121. readyStateValues getReadyState() const { return CLOSED; }
  122. void _dispatch(Callback_Imp &callable) {}
  123. void _dispatchBinary(BytesCallback_Imp &callable) {}
  124. };
  125. class _RealWebSocket : public easywsclient::WebSocket
  126. {
  127. public:
  128. // http://tools.ietf.org/html/rfc6455#section-5.2 Base Framing Protocol
  129. //
  130. // 0 1 2 3
  131. // 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
  132. // +-+-+-+-+-------+-+-------------+-------------------------------+
  133. // |F|R|R|R| opcode|M| Payload len | Extended payload length |
  134. // |I|S|S|S| (4) |A| (7) | (16/64) |
  135. // |N|V|V|V| |S| | (if payload len==126/127) |
  136. // | |1|2|3| |K| | |
  137. // +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
  138. // | Extended payload length continued, if payload len == 127 |
  139. // + - - - - - - - - - - - - - - - +-------------------------------+
  140. // | |Masking-key, if MASK set to 1 |
  141. // +-------------------------------+-------------------------------+
  142. // | Masking-key (continued) | Payload Data |
  143. // +-------------------------------- - - - - - - - - - - - - - - - +
  144. // : Payload Data continued ... :
  145. // + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  146. // | Payload Data continued ... |
  147. // +---------------------------------------------------------------+
  148. struct wsheader_type
  149. {
  150. unsigned header_size;
  151. bool fin;
  152. bool mask;
  153. enum opcode_type
  154. {
  155. CONTINUATION = 0x0,
  156. TEXT_FRAME = 0x1,
  157. BINARY_FRAME = 0x2,
  158. CLOSE = 8,
  159. PING = 9,
  160. PONG = 0xa,
  161. } opcode;
  162. int N0;
  163. uint64_t N;
  164. uint8_t masking_key[4];
  165. };
  166. std::vector<uint8_t> rxbuf;
  167. std::vector<uint8_t> txbuf;
  168. std::vector<uint8_t> receivedData;
  169. socket_t sockfd;
  170. readyStateValues readyState;
  171. bool useMask;
  172. bool isRxBad;
  173. _RealWebSocket(socket_t sockfd, bool useMask)
  174. : sockfd(sockfd), readyState(OPEN), useMask(useMask), isRxBad(false)
  175. {
  176. }
  177. readyStateValues getReadyState() const
  178. {
  179. return readyState;
  180. }
  181. void poll(int timeout)
  182. { // timeout in milliseconds
  183. if (readyState == CLOSED)
  184. {
  185. if (timeout > 0)
  186. {
  187. timeval tv = {timeout / 1000, (timeout % 1000) * 1000};
  188. select(0, NULL, NULL, NULL, &tv);
  189. }
  190. return;
  191. }
  192. if (timeout != 0)
  193. {
  194. fd_set rfds;
  195. fd_set wfds;
  196. timeval tv = {timeout / 1000, (timeout % 1000) * 1000};
  197. FD_ZERO(&rfds);
  198. FD_ZERO(&wfds);
  199. FD_SET(sockfd, &rfds);
  200. if (txbuf.size())
  201. {
  202. FD_SET(sockfd, &wfds);
  203. }
  204. select(sockfd + 1, &rfds, &wfds, 0, timeout > 0 ? &tv : 0);
  205. }
  206. while (true)
  207. {
  208. // FD_ISSET(0, &rfds) will be true
  209. int N = rxbuf.size();
  210. ssize_t ret;
  211. rxbuf.resize(N + 1500);
  212. ret = recv(sockfd, (char *)&rxbuf[0] + N, 1500, 0);
  213. if (false)
  214. {
  215. }
  216. else if (ret < 0 && (socketerrno == SOCKET_EWOULDBLOCK || socketerrno == SOCKET_EAGAIN_EINPROGRESS))
  217. {
  218. rxbuf.resize(N);
  219. break;
  220. }
  221. else if (ret <= 0)
  222. {
  223. rxbuf.resize(N);
  224. closesocket(sockfd);
  225. readyState = CLOSED;
  226. fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", stderr);
  227. break;
  228. }
  229. else
  230. {
  231. rxbuf.resize(N + ret);
  232. }
  233. }
  234. while (txbuf.size())
  235. {
  236. int ret = ::send(sockfd, (char *)&txbuf[0], txbuf.size(), 0);
  237. if (false)
  238. {
  239. } // ??
  240. else if (ret < 0 && (socketerrno == SOCKET_EWOULDBLOCK || socketerrno == SOCKET_EAGAIN_EINPROGRESS))
  241. {
  242. break;
  243. }
  244. else if (ret <= 0)
  245. {
  246. closesocket(sockfd);
  247. readyState = CLOSED;
  248. fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", stderr);
  249. break;
  250. }
  251. else
  252. {
  253. txbuf.erase(txbuf.begin(), txbuf.begin() + ret);
  254. }
  255. }
  256. if (!txbuf.size() && readyState == CLOSING)
  257. {
  258. closesocket(sockfd);
  259. readyState = CLOSED;
  260. }
  261. }
  262. // Callable must have signature: void(const std::string & message).
  263. // Should work with C functions, C++ functors, and C++11 std::function and
  264. // lambda:
  265. //template<class Callable>
  266. //void dispatch(Callable callable)
  267. virtual void _dispatch(Callback_Imp &callable)
  268. {
  269. struct CallbackAdapter : public BytesCallback_Imp
  270. // Adapt void(const std::string<uint8_t>&) to void(const std::string&)
  271. {
  272. Callback_Imp &callable;
  273. CallbackAdapter(Callback_Imp &callable) : callable(callable) {}
  274. void operator()(const std::vector<uint8_t> &message)
  275. {
  276. std::string stringMessage(message.begin(), message.end());
  277. callable(stringMessage);
  278. }
  279. };
  280. CallbackAdapter bytesCallback(callable);
  281. _dispatchBinary(bytesCallback);
  282. }
  283. virtual void _dispatchBinary(BytesCallback_Imp &callable)
  284. {
  285. // TODO: consider acquiring a lock on rxbuf...
  286. if (isRxBad)
  287. {
  288. return;
  289. }
  290. while (true)
  291. {
  292. wsheader_type ws;
  293. if (rxbuf.size() < 2)
  294. {
  295. return; /* Need at least 2 */
  296. }
  297. const uint8_t *data = (uint8_t *)&rxbuf[0]; // peek, but don't consume
  298. ws.fin = (data[0] & 0x80) == 0x80;
  299. ws.opcode = (wsheader_type::opcode_type)(data[0] & 0x0f);
  300. ws.mask = (data[1] & 0x80) == 0x80;
  301. ws.N0 = (data[1] & 0x7f);
  302. ws.header_size = 2 + (ws.N0 == 126 ? 2 : 0) + (ws.N0 == 127 ? 8 : 0) + (ws.mask ? 4 : 0);
  303. if (rxbuf.size() < ws.header_size)
  304. {
  305. return; /* Need: ws.header_size - rxbuf.size() */
  306. }
  307. int i = 0;
  308. if (ws.N0 < 126)
  309. {
  310. ws.N = ws.N0;
  311. i = 2;
  312. }
  313. else if (ws.N0 == 126)
  314. {
  315. ws.N = 0;
  316. ws.N |= ((uint64_t)data[2]) << 8;
  317. ws.N |= ((uint64_t)data[3]) << 0;
  318. i = 4;
  319. }
  320. else if (ws.N0 == 127)
  321. {
  322. ws.N = 0;
  323. ws.N |= ((uint64_t)data[2]) << 56;
  324. ws.N |= ((uint64_t)data[3]) << 48;
  325. ws.N |= ((uint64_t)data[4]) << 40;
  326. ws.N |= ((uint64_t)data[5]) << 32;
  327. ws.N |= ((uint64_t)data[6]) << 24;
  328. ws.N |= ((uint64_t)data[7]) << 16;
  329. ws.N |= ((uint64_t)data[8]) << 8;
  330. ws.N |= ((uint64_t)data[9]) << 0;
  331. i = 10;
  332. if (ws.N & 0x8000000000000000ull)
  333. {
  334. // https://tools.ietf.org/html/rfc6455 writes the "the most
  335. // significant bit MUST be 0."
  336. //
  337. // We can't drop the frame, because (1) we don't we don't
  338. // know how much data to skip over to find the next header,
  339. // and (2) this would be an impractically long length, even
  340. // if it were valid. So just close() and return immediately
  341. // for now.
  342. isRxBad = true;
  343. fprintf(stderr, "ERROR: Frame has invalid frame length. Closing.\n");
  344. close();
  345. return;
  346. }
  347. }
  348. if (ws.mask)
  349. {
  350. ws.masking_key[0] = ((uint8_t)data[i + 0]) << 0;
  351. ws.masking_key[1] = ((uint8_t)data[i + 1]) << 0;
  352. ws.masking_key[2] = ((uint8_t)data[i + 2]) << 0;
  353. ws.masking_key[3] = ((uint8_t)data[i + 3]) << 0;
  354. }
  355. else
  356. {
  357. ws.masking_key[0] = 0;
  358. ws.masking_key[1] = 0;
  359. ws.masking_key[2] = 0;
  360. ws.masking_key[3] = 0;
  361. }
  362. // Note: The checks above should hopefully ensure this addition
  363. // cannot overflow:
  364. if (rxbuf.size() < ws.header_size + ws.N)
  365. {
  366. return; /* Need: ws.header_size+ws.N - rxbuf.size() */
  367. }
  368. // We got a whole message, now do something with it:
  369. if (false)
  370. {
  371. }
  372. else if (
  373. ws.opcode == wsheader_type::TEXT_FRAME || ws.opcode == wsheader_type::BINARY_FRAME || ws.opcode == wsheader_type::CONTINUATION)
  374. {
  375. if (ws.mask)
  376. {
  377. for (size_t i = 0; i != ws.N; ++i)
  378. {
  379. rxbuf[i + ws.header_size] ^= ws.masking_key[i & 0x3];
  380. }
  381. }
  382. receivedData.insert(receivedData.end(), rxbuf.begin() + ws.header_size, rxbuf.begin() + ws.header_size + (size_t)ws.N); // just feed
  383. if (ws.fin)
  384. {
  385. callable((const std::vector<uint8_t>)receivedData);
  386. receivedData.erase(receivedData.begin(), receivedData.end());
  387. std::vector<uint8_t>().swap(receivedData); // free memory
  388. }
  389. }
  390. else if (ws.opcode == wsheader_type::PING)
  391. {
  392. if (ws.mask)
  393. {
  394. for (size_t i = 0; i != ws.N; ++i)
  395. {
  396. rxbuf[i + ws.header_size] ^= ws.masking_key[i & 0x3];
  397. }
  398. }
  399. std::string data(rxbuf.begin() + ws.header_size, rxbuf.begin() + ws.header_size + (size_t)ws.N);
  400. sendData(wsheader_type::PONG, data.size(), data.begin(), data.end());
  401. }
  402. else if (ws.opcode == wsheader_type::PONG)
  403. {
  404. }
  405. else if (ws.opcode == wsheader_type::CLOSE)
  406. {
  407. close();
  408. }
  409. else
  410. {
  411. fprintf(stderr, "ERROR: Got unexpected WebSocket message.\n");
  412. close();
  413. }
  414. rxbuf.erase(rxbuf.begin(), rxbuf.begin() + ws.header_size + (size_t)ws.N);
  415. }
  416. }
  417. void sendPing()
  418. {
  419. std::string empty;
  420. sendData(wsheader_type::PING, empty.size(), empty.begin(), empty.end());
  421. }
  422. void send(const std::string &message)
  423. {
  424. sendData(wsheader_type::TEXT_FRAME, message.size(), message.begin(), message.end());
  425. }
  426. void sendBinary(const std::string &message)
  427. {
  428. sendData(wsheader_type::BINARY_FRAME, message.size(), message.begin(), message.end());
  429. }
  430. void sendBinary(const std::vector<uint8_t> &message)
  431. {
  432. sendData(wsheader_type::BINARY_FRAME, message.size(), message.begin(), message.end());
  433. }
  434. template <class Iterator>
  435. void sendData(wsheader_type::opcode_type type, uint64_t message_size, Iterator message_begin, Iterator message_end)
  436. {
  437. // TODO:
  438. // Masking key should (must) be derived from a high quality random
  439. // number generator, to mitigate attacks on non-WebSocket friendly
  440. // middleware:
  441. const uint8_t masking_key[4] = {0x12, 0x34, 0x56, 0x78};
  442. // TODO: consider acquiring a lock on txbuf...
  443. if (readyState == CLOSING || readyState == CLOSED)
  444. {
  445. return;
  446. }
  447. std::vector<uint8_t> header;
  448. header.assign(2 + (message_size >= 126 ? 2 : 0) + (message_size >= 65536 ? 6 : 0) + (useMask ? 4 : 0), 0);
  449. header[0] = 0x80 | type;
  450. if (false)
  451. {
  452. }
  453. else if (message_size < 126)
  454. {
  455. header[1] = (message_size & 0xff) | (useMask ? 0x80 : 0);
  456. if (useMask)
  457. {
  458. header[2] = masking_key[0];
  459. header[3] = masking_key[1];
  460. header[4] = masking_key[2];
  461. header[5] = masking_key[3];
  462. }
  463. }
  464. else if (message_size < 65536)
  465. {
  466. header[1] = 126 | (useMask ? 0x80 : 0);
  467. header[2] = (message_size >> 8) & 0xff;
  468. header[3] = (message_size >> 0) & 0xff;
  469. if (useMask)
  470. {
  471. header[4] = masking_key[0];
  472. header[5] = masking_key[1];
  473. header[6] = masking_key[2];
  474. header[7] = masking_key[3];
  475. }
  476. }
  477. else
  478. { // TODO: run coverage testing here
  479. header[1] = 127 | (useMask ? 0x80 : 0);
  480. header[2] = (message_size >> 56) & 0xff;
  481. header[3] = (message_size >> 48) & 0xff;
  482. header[4] = (message_size >> 40) & 0xff;
  483. header[5] = (message_size >> 32) & 0xff;
  484. header[6] = (message_size >> 24) & 0xff;
  485. header[7] = (message_size >> 16) & 0xff;
  486. header[8] = (message_size >> 8) & 0xff;
  487. header[9] = (message_size >> 0) & 0xff;
  488. if (useMask)
  489. {
  490. header[10] = masking_key[0];
  491. header[11] = masking_key[1];
  492. header[12] = masking_key[2];
  493. header[13] = masking_key[3];
  494. }
  495. }
  496. // N.B. - txbuf will keep growing until it can be transmitted over the socket:
  497. txbuf.insert(txbuf.end(), header.begin(), header.end());
  498. txbuf.insert(txbuf.end(), message_begin, message_end);
  499. if (useMask)
  500. {
  501. size_t message_offset = txbuf.size() - message_size;
  502. for (size_t i = 0; i != message_size; ++i)
  503. {
  504. txbuf[message_offset + i] ^= masking_key[i & 0x3];
  505. }
  506. }
  507. }
  508. void close()
  509. {
  510. if (readyState == CLOSING || readyState == CLOSED)
  511. {
  512. return;
  513. }
  514. readyState = CLOSING;
  515. uint8_t closeFrame[6] = {0x88, 0x80, 0x00, 0x00, 0x00, 0x00}; // last 4 bytes are a masking key
  516. std::vector<uint8_t> header(closeFrame, closeFrame + 6);
  517. txbuf.insert(txbuf.end(), header.begin(), header.end());
  518. }
  519. };
  520. easywsclient::WebSocket::pointer from_url(const std::string &url, bool useMask, const std::string &origin, bool internal = false)
  521. {
  522. char host[512];
  523. int port;
  524. char path[512];
  525. if (url.size() >= 512)
  526. {
  527. fprintf(stderr, "ERROR: url size limit exceeded: %s\n", url.c_str());
  528. return NULL;
  529. }
  530. if (origin.size() >= 200)
  531. {
  532. fprintf(stderr, "ERROR: origin size limit exceeded: %s\n", origin.c_str());
  533. return NULL;
  534. }
  535. if (false)
  536. {
  537. }
  538. else if (sscanf(url.c_str(), "ws://%[^:/]:%d/%s", host, &port, path) == 3)
  539. {
  540. }
  541. else if (sscanf(url.c_str(), "ws://%[^:/]/%s", host, path) == 2)
  542. {
  543. port = 80;
  544. }
  545. else if (sscanf(url.c_str(), "ws://%[^:/]:%d", host, &port) == 2)
  546. {
  547. path[0] = '\0';
  548. }
  549. else if (sscanf(url.c_str(), "ws://%[^:/]", host) == 1)
  550. {
  551. port = 80;
  552. path[0] = '\0';
  553. }
  554. else
  555. {
  556. fprintf(stderr, "ERROR: Could not parse WebSocket url: %s\n", url.c_str());
  557. return NULL;
  558. }
  559. //fprintf(stderr, "easywsclient: connecting: host=%s port=%d path=/%s\n", host, port, path);
  560. socket_t sockfd = hostname_connect(host, port);
  561. if (sockfd == INVALID_SOCKET)
  562. {
  563. fprintf(stderr, "Unable to connect to %s:%d\n", host, port);
  564. return NULL;
  565. }
  566. {
  567. // XXX: this should be done non-blocking,
  568. char line[1024];
  569. int status;
  570. int i;
  571. snprintf(line, 1024, "GET /%s HTTP/1.1\r\n", path);
  572. ::send(sockfd, line, strlen(line), 0);
  573. if (port == 80)
  574. {
  575. snprintf(line, 1024, "Host: %s\r\n", host);
  576. ::send(sockfd, line, strlen(line), 0);
  577. }
  578. else
  579. {
  580. snprintf(line, 1024, "Host: %s:%d\r\n", host, port);
  581. ::send(sockfd, line, strlen(line), 0);
  582. }
  583. snprintf(line, 1024, "Upgrade: websocket\r\n");
  584. ::send(sockfd, line, strlen(line), 0);
  585. snprintf(line, 1024, "Connection: Upgrade\r\n");
  586. ::send(sockfd, line, strlen(line), 0);
  587. if (!origin.empty())
  588. {
  589. snprintf(line, 1024, "Origin: %s\r\n", origin.c_str());
  590. ::send(sockfd, line, strlen(line), 0);
  591. }
  592. snprintf(line, 1024, "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n");
  593. ::send(sockfd, line, strlen(line), 0);
  594. if (internal)
  595. {
  596. snprintf(line, 1024, "internal: true\r\n");
  597. ::send(sockfd, line, strlen(line), 0);
  598. }
  599. snprintf(line, 1024, "Sec-WebSocket-Version: 13\r\n");
  600. ::send(sockfd, line, strlen(line), 0);
  601. snprintf(line, 1024, "\r\n");
  602. ::send(sockfd, line, strlen(line), 0);
  603. for (i = 0; i < 2 || (i < 1023 && line[i - 2] != '\r' && line[i - 1] != '\n'); ++i)
  604. {
  605. if (recv(sockfd, line + i, 1, 0) == 0)
  606. {
  607. return NULL;
  608. }
  609. }
  610. line[i] = 0;
  611. if (i == 1023)
  612. {
  613. fprintf(stderr, "ERROR: Got invalid status line connecting to: %s\n", url.c_str());
  614. return NULL;
  615. }
  616. if (sscanf(line, "HTTP/1.1 %d", &status) != 1 || status != 101)
  617. {
  618. fprintf(stderr, "ERROR: Got bad status connecting to %s: %s", url.c_str(), line);
  619. return NULL;
  620. }
  621. // TODO: verify response headers,
  622. while (true)
  623. {
  624. for (i = 0; i < 2 || (i < 1023 && line[i - 2] != '\r' && line[i - 1] != '\n'); ++i)
  625. {
  626. if (recv(sockfd, line + i, 1, 0) == 0)
  627. {
  628. return NULL;
  629. }
  630. }
  631. if (line[0] == '\r' && line[1] == '\n')
  632. {
  633. break;
  634. }
  635. }
  636. }
  637. int flag = 1;
  638. setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)); // Disable Nagle's algorithm
  639. #ifdef _WIN32
  640. u_long on = 1;
  641. ioctlsocket(sockfd, FIONBIO, &on);
  642. #else
  643. fcntl(sockfd, F_SETFL, O_NONBLOCK);
  644. #endif
  645. //fprintf(stderr, "Connected to: %s\n", url.c_str());
  646. return easywsclient::WebSocket::pointer(new _RealWebSocket(sockfd, useMask));
  647. }
  648. } // end of module-only namespace
  649. namespace easywsclient
  650. {
  651. WebSocket::pointer WebSocket::create_dummy()
  652. {
  653. static pointer dummy = pointer(new _DummyWebSocket);
  654. return dummy;
  655. }
  656. WebSocket::pointer WebSocket::from_url(const std::string &url, const std::string &origin, bool internal)
  657. {
  658. return ::from_url(url, true, origin, internal);
  659. }
  660. WebSocket::pointer WebSocket::from_url_no_mask(const std::string &url, const std::string &origin)
  661. {
  662. return ::from_url(url, false, origin);
  663. }
  664. } // namespace easywsclient