PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/hphp/runtime/ext/ext_socket.cpp

http://github.com/facebook/hiphop-php
C++ | 1267 lines | 1070 code | 152 blank | 45 comment | 203 complexity | 6001964cd246e6c05a1cf89e59d5ea30 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, MIT, LGPL-2.0, Apache-2.0
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
  6. | Copyright (c) 1997-2010 The PHP Group |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 3.01 of the PHP license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.php.net/license/3_01.txt |
  12. | If you did not receive a copy of the PHP license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@php.net so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. */
  17. #include "hphp/runtime/ext/ext_socket.h"
  18. #include "hphp/runtime/base/socket.h"
  19. #include "hphp/runtime/base/ssl-socket.h"
  20. #include "hphp/runtime/server/server-stats.h"
  21. #include "hphp/util/logger.h"
  22. #include "folly/String.h"
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <netdb.h>
  26. #include <netinet/in.h>
  27. #include <netinet/tcp.h>
  28. #include <sys/un.h>
  29. #include <arpa/inet.h>
  30. #include <sys/time.h>
  31. #include <unistd.h>
  32. #include <errno.h>
  33. #include <fcntl.h>
  34. #include <signal.h>
  35. #include <sys/uio.h>
  36. #include "hphp/util/network.h"
  37. #include <poll.h>
  38. #define PHP_NORMAL_READ 0x0001
  39. #define PHP_BINARY_READ 0x0002
  40. namespace HPHP {
  41. IMPLEMENT_DEFAULT_EXTENSION(sockets);
  42. ///////////////////////////////////////////////////////////////////////////////
  43. // helpers
  44. static void check_socket_parameters(int &domain, int &type) {
  45. if (domain != AF_UNIX && domain != AF_INET6 && domain != AF_INET) {
  46. raise_warning("invalid socket domain [%d] specified for argument 1, "
  47. "assuming AF_INET", domain);
  48. domain = AF_INET;
  49. }
  50. if (type > 10) {
  51. raise_warning("invalid socket type [%d] specified for argument 2, "
  52. "assuming SOCK_STREAM", type);
  53. type = SOCK_STREAM;
  54. }
  55. }
  56. static bool get_sockaddr(sockaddr *sa, socklen_t salen,
  57. Variant &address, Variant &port) {
  58. switch (sa->sa_family) {
  59. case AF_INET6:
  60. {
  61. struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
  62. char addr6[INET6_ADDRSTRLEN+1];
  63. inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN);
  64. address = String(addr6, CopyString);
  65. port = htons(sin6->sin6_port);
  66. }
  67. return true;
  68. case AF_INET:
  69. {
  70. struct sockaddr_in *sin = (struct sockaddr_in *)sa;
  71. address = String(Util::safe_inet_ntoa(sin->sin_addr));
  72. port = htons(sin->sin_port);
  73. }
  74. return true;
  75. case AF_UNIX:
  76. {
  77. // NB: an unnamed socket has no path, and sun_path should not be
  78. // inspected. In that case the length is just the size of the
  79. // struct without sun_path.
  80. struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
  81. if (salen > offsetof(sockaddr_un, sun_path)) {
  82. address = String(s_un->sun_path, CopyString);
  83. }
  84. }
  85. return true;
  86. default:
  87. break;
  88. }
  89. raise_warning("Unsupported address family %d", sa->sa_family);
  90. return false;
  91. }
  92. static bool php_set_inet6_addr(struct sockaddr_in6 *sin6, const char *address,
  93. Socket *sock) {
  94. struct in6_addr tmp;
  95. struct addrinfo hints;
  96. struct addrinfo *addrinfo = NULL;
  97. if (inet_pton(AF_INET6, address, &tmp)) {
  98. memcpy(&(sin6->sin6_addr.s6_addr), &(tmp.s6_addr),
  99. sizeof(struct in6_addr));
  100. } else {
  101. memset(&hints, 0, sizeof(struct addrinfo));
  102. hints.ai_family = PF_INET6;
  103. getaddrinfo(address, NULL, &hints, &addrinfo);
  104. if (!addrinfo) {
  105. SOCKET_ERROR(sock, "Host lookup failed", (-10000 - h_errno));
  106. return false;
  107. }
  108. if (addrinfo->ai_family != PF_INET6 ||
  109. addrinfo->ai_addrlen != sizeof(struct sockaddr_in6)) {
  110. raise_warning("Host lookup failed: Non AF_INET6 domain "
  111. "returned on AF_INET6 socket");
  112. freeaddrinfo(addrinfo);
  113. return false;
  114. }
  115. memcpy(&(sin6->sin6_addr.s6_addr),
  116. ((struct sockaddr_in6*)(addrinfo->ai_addr))->sin6_addr.s6_addr,
  117. sizeof(struct in6_addr));
  118. freeaddrinfo(addrinfo);
  119. }
  120. return true;
  121. }
  122. static bool php_set_inet_addr(struct sockaddr_in *sin, const char *address,
  123. Socket *sock) {
  124. struct in_addr tmp;
  125. if (inet_aton(address, &tmp)) {
  126. sin->sin_addr.s_addr = tmp.s_addr;
  127. } else {
  128. Util::HostEnt result;
  129. if (!Util::safe_gethostbyname(address, result)) {
  130. /* Note: < -10000 indicates a host lookup error */
  131. SOCKET_ERROR(sock, "Host lookup failed", (-10000 - result.herr));
  132. return false;
  133. }
  134. if (result.hostbuf.h_addrtype != AF_INET) {
  135. raise_warning("Host lookup failed: Non AF_INET domain "
  136. "returned on AF_INET socket");
  137. return false;
  138. }
  139. memcpy(&(sin->sin_addr.s_addr), result.hostbuf.h_addr_list[0],
  140. result.hostbuf.h_length);
  141. }
  142. return true;
  143. }
  144. static bool set_sockaddr(sockaddr_storage &sa_storage, Socket *sock,
  145. const char *addr, int port,
  146. struct sockaddr *&sa_ptr, size_t &sa_size) {
  147. struct sockaddr *sock_type = (struct sockaddr*) &sa_storage;
  148. switch (sock->getType()) {
  149. case AF_UNIX:
  150. {
  151. struct sockaddr_un *sa = (struct sockaddr_un *)sock_type;
  152. memset(sa, 0, sizeof(sa_storage));
  153. sa->sun_family = AF_UNIX;
  154. snprintf(sa->sun_path, 108, "%s", addr);
  155. sa_ptr = (struct sockaddr *)sa;
  156. sa_size = SUN_LEN(sa);
  157. }
  158. break;
  159. case AF_INET:
  160. {
  161. struct sockaddr_in *sa = (struct sockaddr_in *)sock_type;
  162. memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */
  163. sa->sin_family = AF_INET;
  164. sa->sin_port = htons((unsigned short) port);
  165. if (!php_set_inet_addr(sa, addr, sock)) {
  166. return false;
  167. }
  168. sa_ptr = (struct sockaddr *)sa;
  169. sa_size = sizeof(struct sockaddr_in);
  170. }
  171. break;
  172. case AF_INET6:
  173. {
  174. struct sockaddr_in6 *sa = (struct sockaddr_in6 *)sock_type;
  175. memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */
  176. sa->sin6_family = AF_INET6;
  177. sa->sin6_port = htons((unsigned short) port);
  178. if (!php_set_inet6_addr(sa, addr, sock)) {
  179. return false;
  180. }
  181. sa_ptr = (struct sockaddr *)sa;
  182. sa_size = sizeof(struct sockaddr_in6);
  183. }
  184. break;
  185. default:
  186. raise_warning("unsupported socket type '%d', must be "
  187. "AF_UNIX, AF_INET, or AF_INET6", sock->getType());
  188. return false;
  189. }
  190. return true;
  191. }
  192. static void sock_array_to_fd_set(CArrRef sockets, pollfd *fds, int &nfds,
  193. short flag) {
  194. assert(fds);
  195. for (ArrayIter iter(sockets); iter; ++iter) {
  196. File *sock = iter.second().toResource().getTyped<File>();
  197. pollfd &fd = fds[nfds++];
  198. fd.fd = sock->fd();
  199. fd.events = flag;
  200. fd.revents = 0;
  201. }
  202. }
  203. static void sock_array_from_fd_set(Variant &sockets, pollfd *fds, int &nfds,
  204. int &count, short flag) {
  205. assert(sockets.is(KindOfArray));
  206. Array sock_array = sockets.toArray();
  207. Array ret;
  208. for (ArrayIter iter(sock_array); iter; ++iter) {
  209. pollfd &fd = fds[nfds++];
  210. assert(fd.fd == iter.second().toResource().getTyped<File>()->fd());
  211. if (fd.revents & flag) {
  212. ret.append(iter.second());
  213. count++;
  214. }
  215. }
  216. sockets = ret;
  217. }
  218. static int php_read(Socket *sock, void *buf, int maxlen, int flags) {
  219. int m = fcntl(sock->fd(), F_GETFL);
  220. if (m < 0) {
  221. return m;
  222. }
  223. int nonblock = (m & O_NONBLOCK);
  224. m = 0;
  225. char *t = (char *)buf;
  226. *t = '\0';
  227. int n = 0;
  228. int no_read = 0;
  229. while (*t != '\n' && *t != '\r' && n < maxlen) {
  230. if (m > 0) {
  231. t++;
  232. n++;
  233. } else if (m == 0) {
  234. no_read++;
  235. if (nonblock && no_read >= 2) {
  236. return n;
  237. /* The first pass, m always is 0, so no_read becomes 1
  238. * in the first pass. no_read becomes 2 in the second pass,
  239. * and if this is nonblocking, we should return.. */
  240. }
  241. if (no_read > 200) {
  242. errno = ECONNRESET;
  243. return -1;
  244. }
  245. }
  246. if (n < maxlen) {
  247. m = recv(sock->fd(), (void *)t, 1, flags);
  248. }
  249. if (errno != 0 && errno != ESPIPE && errno != EAGAIN) {
  250. return -1;
  251. }
  252. errno = 0;
  253. }
  254. if (n < maxlen) {
  255. n++;
  256. /* The only reasons it makes it to here is
  257. * if '\n' or '\r' are encountered. So, increase
  258. * the return by 1 to make up for the lack of the
  259. * '\n' or '\r' in the count (since read() takes
  260. * place at the end of the loop..) */
  261. }
  262. return n;
  263. }
  264. static bool create_new_socket(const Util::HostURL &hosturl,
  265. Variant &errnum, Variant &errstr, Resource &ret,
  266. Socket *&sock, double timeout) {
  267. int domain = hosturl.isIPv6() ? AF_INET6 : AF_INET;
  268. int type = SOCK_STREAM;
  269. const std::string scheme = hosturl.getScheme();
  270. if (scheme == "udp" || scheme == "udg") {
  271. type = SOCK_DGRAM;
  272. } else if (scheme == "unix") {
  273. domain = AF_UNIX;
  274. }
  275. sock = new Socket(socket(domain, type, 0), domain,
  276. hosturl.getHost().c_str(), hosturl.getPort(), timeout);
  277. ret = Resource(sock);
  278. if (!sock->valid()) {
  279. SOCKET_ERROR(sock, "unable to create socket", errno);
  280. errnum = sock->getError();
  281. errstr = String(folly::errnoStr(sock->getError()).toStdString());
  282. return false;
  283. }
  284. return true;
  285. }
  286. ///////////////////////////////////////////////////////////////////////////////
  287. Variant f_socket_create(int domain, int type, int protocol) {
  288. check_socket_parameters(domain, type);
  289. int socketId = socket(domain, type, protocol);
  290. if (socketId == -1) {
  291. Socket dummySock; // for setting last socket error
  292. SOCKET_ERROR((&dummySock), "Unable to create socket", errno);
  293. return false;
  294. }
  295. Socket *sock = new Socket(socketId, domain);
  296. Resource ret(sock);
  297. return ret;
  298. }
  299. Variant f_socket_create_listen(int port, int backlog /* = 128 */) {
  300. Util::HostEnt result;
  301. if (!Util::safe_gethostbyname("0.0.0.0", result)) {
  302. return false;
  303. }
  304. struct sockaddr_in la;
  305. memcpy((char *) &la.sin_addr, result.hostbuf.h_addr,
  306. result.hostbuf.h_length);
  307. la.sin_family = result.hostbuf.h_addrtype;
  308. la.sin_port = htons((unsigned short)port);
  309. Socket *sock = new Socket(socket(PF_INET, SOCK_STREAM, 0), PF_INET,
  310. "0.0.0.0", port);
  311. Resource ret(sock);
  312. if (!sock->valid()) {
  313. SOCKET_ERROR(sock, "unable to create listening socket", errno);
  314. return false;
  315. }
  316. if (::bind(sock->fd(), (struct sockaddr *)&la, sizeof(la)) < 0) {
  317. SOCKET_ERROR(sock, "unable to bind to given address", errno);
  318. return false;
  319. }
  320. if (listen(sock->fd(), backlog) < 0) {
  321. SOCKET_ERROR(sock, "unable to listen on socket", errno);
  322. return false;
  323. }
  324. return ret;
  325. }
  326. bool f_socket_create_pair(int domain, int type, int protocol, VRefParam fd) {
  327. check_socket_parameters(domain, type);
  328. int fds_array[2];
  329. if (socketpair(domain, type, protocol, fds_array) != 0) {
  330. Socket dummySock; // for setting last socket error
  331. SOCKET_ERROR((&dummySock), "unable to create socket pair", errno);
  332. return false;
  333. }
  334. Array ret;
  335. ret.set(0, Resource(new Socket(fds_array[0], domain)));
  336. ret.set(1, Resource(new Socket(fds_array[1], domain)));
  337. fd = ret;
  338. return true;
  339. }
  340. const StaticString
  341. s_l_onoff("l_onoff"),
  342. s_l_linger("l_linger"),
  343. s_sec("sec"),
  344. s_usec("usec");
  345. Variant f_socket_get_option(CResRef socket, int level, int optname) {
  346. Socket *sock = socket.getTyped<Socket>();
  347. Array ret;
  348. socklen_t optlen;
  349. switch (optname) {
  350. case SO_LINGER:
  351. {
  352. struct linger linger_val;
  353. optlen = sizeof(linger_val);
  354. if (getsockopt(sock->fd(), level, optname, (char*)&linger_val,
  355. &optlen) != 0) {
  356. SOCKET_ERROR(sock, "unable to retrieve socket option", errno);
  357. return false;
  358. }
  359. ret.set(s_l_onoff, linger_val.l_onoff);
  360. ret.set(s_l_linger, linger_val.l_linger);
  361. }
  362. break;
  363. case SO_RCVTIMEO:
  364. case SO_SNDTIMEO:
  365. {
  366. struct timeval tv;
  367. optlen = sizeof(tv);
  368. if (getsockopt(sock->fd(), level, optname, (char*)&tv, &optlen) != 0) {
  369. SOCKET_ERROR(sock, "unable to retrieve socket option", errno);
  370. return false;
  371. }
  372. ret.set(s_sec, (int)tv.tv_sec);
  373. ret.set(s_usec, (int)tv.tv_usec);
  374. }
  375. break;
  376. default:
  377. {
  378. int other_val;
  379. optlen = sizeof(other_val);
  380. if (getsockopt(sock->fd(), level, optname, (char*)&other_val, &optlen)) {
  381. SOCKET_ERROR(sock, "unable to retrieve socket option", errno);
  382. return false;
  383. }
  384. return other_val;
  385. }
  386. }
  387. return ret;
  388. }
  389. bool f_socket_getpeername(CResRef socket, VRefParam address,
  390. VRefParam port /* = null */) {
  391. Socket *sock = socket.getTyped<Socket>();
  392. sockaddr_storage sa_storage;
  393. socklen_t salen = sizeof(sockaddr_storage);
  394. struct sockaddr *sa = (struct sockaddr *)&sa_storage;
  395. if (getpeername(sock->fd(), sa, &salen) < 0) {
  396. SOCKET_ERROR(sock, "unable to retrieve peer name", errno);
  397. return false;
  398. }
  399. return get_sockaddr(sa, salen, address, port);
  400. }
  401. bool f_socket_getsockname(CResRef socket, VRefParam address,
  402. VRefParam port /* = null */) {
  403. Socket *sock = socket.getTyped<Socket>();
  404. sockaddr_storage sa_storage;
  405. socklen_t salen = sizeof(sockaddr_storage);
  406. struct sockaddr *sa = (struct sockaddr *)&sa_storage;
  407. if (getsockname(sock->fd(), sa, &salen) < 0) {
  408. SOCKET_ERROR(sock, "unable to retrieve peer name", errno);
  409. return false;
  410. }
  411. return get_sockaddr(sa, salen, address, port);
  412. }
  413. bool f_socket_set_block(CResRef socket) {
  414. Socket *sock = socket.getTyped<Socket>();
  415. return sock->setBlocking(true);
  416. }
  417. bool f_socket_set_nonblock(CResRef socket) {
  418. Socket *sock = socket.getTyped<Socket>();
  419. return sock->setBlocking(false);
  420. }
  421. bool f_socket_set_option(CResRef socket, int level, int optname,
  422. CVarRef optval) {
  423. Socket *sock = socket.getTyped<Socket>();
  424. struct linger lv;
  425. struct timeval tv;
  426. int ov;
  427. int optlen;
  428. void *opt_ptr;
  429. switch (optname) {
  430. case SO_LINGER:
  431. {
  432. Array value = optval.toArray();
  433. if (!value.exists(s_l_onoff)) {
  434. raise_warning("no key \"l_onoff\" passed in optval");
  435. return false;
  436. }
  437. if (!value.exists(s_l_linger)) {
  438. raise_warning("no key \"l_linger\" passed in optval");
  439. return false;
  440. }
  441. lv.l_onoff = (unsigned short)value[s_l_onoff].toInt32();
  442. lv.l_linger = (unsigned short)value[s_l_linger].toInt32();
  443. optlen = sizeof(lv);
  444. opt_ptr = &lv;
  445. }
  446. break;
  447. case SO_RCVTIMEO:
  448. case SO_SNDTIMEO:
  449. {
  450. Array value = optval.toArray();
  451. if (!value.exists(s_sec)) {
  452. raise_warning("no key \"sec\" passed in optval");
  453. return false;
  454. }
  455. if (!value.exists(s_usec)) {
  456. raise_warning("no key \"usec\" passed in optval");
  457. return false;
  458. }
  459. tv.tv_sec = value[s_sec].toInt32();
  460. tv.tv_usec = value[s_usec].toInt32();
  461. if (tv.tv_usec >= 1000000) {
  462. tv.tv_sec += tv.tv_usec / 1000000;
  463. tv.tv_usec %= 1000000;
  464. }
  465. optlen = sizeof(tv);
  466. opt_ptr = &tv;
  467. sock->setTimeout(tv);
  468. }
  469. break;
  470. default:
  471. ov = optval.toInt32();
  472. optlen = sizeof(ov);
  473. opt_ptr = &ov;
  474. break;
  475. }
  476. if (setsockopt(sock->fd(), level, optname, opt_ptr, optlen) != 0) {
  477. SOCKET_ERROR(sock, "unable to set socket option", errno);
  478. return false;
  479. }
  480. return true;
  481. }
  482. bool f_socket_connect(CResRef socket, const String& address, int port /* = 0 */) {
  483. Socket *sock = socket.getTyped<Socket>();
  484. switch (sock->getType()) {
  485. case AF_INET6:
  486. case AF_INET:
  487. if (port == 0) {
  488. raise_warning("Socket of type AF_INET/6 requires 3 arguments");
  489. return false;
  490. }
  491. break;
  492. default:
  493. break;
  494. }
  495. const char *addr = address.data();
  496. sockaddr_storage sa_storage;
  497. struct sockaddr *sa_ptr;
  498. size_t sa_size;
  499. if (!set_sockaddr(sa_storage, sock, addr, port, sa_ptr, sa_size)) {
  500. return false;
  501. }
  502. IOStatusHelper io("socket::connect", address.data(), port);
  503. int retval = connect(sock->fd(), sa_ptr, sa_size);
  504. if (retval != 0) {
  505. std::string msg = "unable to connect to ";
  506. msg += addr;
  507. msg += ":";
  508. msg += boost::lexical_cast<std::string>(port);
  509. SOCKET_ERROR(sock, msg.c_str(), errno);
  510. return false;
  511. }
  512. return true;
  513. }
  514. bool f_socket_bind(CResRef socket, const String& address, int port /* = 0 */) {
  515. Socket *sock = socket.getTyped<Socket>();
  516. const char *addr = address.data();
  517. sockaddr_storage sa_storage;
  518. struct sockaddr *sa_ptr;
  519. size_t sa_size;
  520. if (!set_sockaddr(sa_storage, sock, addr, port, sa_ptr, sa_size)) {
  521. return false;
  522. }
  523. long retval = ::bind(sock->fd(), sa_ptr, sa_size);
  524. if (retval != 0) {
  525. std::string msg = "unable to bind address";
  526. msg += addr;
  527. msg += ":";
  528. msg += boost::lexical_cast<std::string>(port);
  529. SOCKET_ERROR(sock, msg.c_str(), errno);
  530. return false;
  531. }
  532. return true;
  533. }
  534. bool f_socket_listen(CResRef socket, int backlog /* = 0 */) {
  535. Socket *sock = socket.getTyped<Socket>();
  536. if (listen(sock->fd(), backlog) != 0) {
  537. SOCKET_ERROR(sock, "unable to listen on socket", errno);
  538. return false;
  539. }
  540. return true;
  541. }
  542. Variant f_socket_select(VRefParam read, VRefParam write, VRefParam except,
  543. CVarRef vtv_sec, int tv_usec /* = 0 */) {
  544. int count = 0;
  545. if (!read.isNull()) {
  546. count += read.toArray().size();
  547. }
  548. if (!write.isNull()) {
  549. count += write.toArray().size();
  550. }
  551. if (!except.isNull()) {
  552. count += except.toArray().size();
  553. }
  554. if (!count) {
  555. return false;
  556. }
  557. struct pollfd *fds = (struct pollfd *)calloc(count, sizeof(struct pollfd));
  558. count = 0;
  559. if (!read.isNull()) {
  560. sock_array_to_fd_set(read.toArray(), fds, count, POLLIN);
  561. }
  562. if (!write.isNull()) {
  563. sock_array_to_fd_set(write.toArray(), fds, count, POLLOUT);
  564. }
  565. if (!except.isNull()) {
  566. sock_array_to_fd_set(except.toArray(), fds, count, POLLPRI);
  567. }
  568. IOStatusHelper io("socket_select");
  569. int timeout_ms = -1;
  570. if (!vtv_sec.isNull()) {
  571. timeout_ms = vtv_sec.toInt32() * 1000 + tv_usec / 1000;
  572. }
  573. /* slight hack to support buffered data; if there is data sitting in the
  574. * read buffer of any of the streams in the read array, let's pretend
  575. * that we selected, but return only the readable sockets */
  576. if (!read.isNull()) {
  577. auto hasData = Array::Create();
  578. for (ArrayIter iter(read.toArray()); iter; ++iter) {
  579. File *file = iter.second().toResource().getTyped<File>();
  580. if (file->bufferedLen() > 0) {
  581. hasData.append(iter.second());
  582. }
  583. }
  584. if (hasData.size() > 0) {
  585. if (!write.isNull()) {
  586. write = Array::Create();
  587. }
  588. if (!except.isNull()) {
  589. except = Array::Create();
  590. }
  591. read = hasData;
  592. return hasData.size();
  593. }
  594. }
  595. int retval = poll(fds, count, timeout_ms);
  596. if (retval == -1) {
  597. raise_warning("unable to select [%d]: %s", errno,
  598. folly::errnoStr(errno).c_str());
  599. free(fds);
  600. return false;
  601. }
  602. count = 0;
  603. int nfds = 0;
  604. if (!read.isNull()) {
  605. sock_array_from_fd_set(read, fds, nfds, count, POLLIN|POLLERR|POLLHUP);
  606. }
  607. if (!write.isNull()) {
  608. sock_array_from_fd_set(write, fds, nfds, count, POLLOUT|POLLERR);
  609. }
  610. if (!except.isNull()) {
  611. sock_array_from_fd_set(except, fds, nfds, count, POLLPRI|POLLERR);
  612. }
  613. free(fds);
  614. return count;
  615. }
  616. Variant f_socket_server(const String& hostname, int port /* = -1 */,
  617. VRefParam errnum /* = null */,
  618. VRefParam errstr /* = null */) {
  619. Util::HostURL hosturl(static_cast<const std::string>(hostname), port);
  620. return socket_server_impl(hosturl,
  621. k_STREAM_SERVER_BIND|k_STREAM_SERVER_LISTEN,
  622. errnum, errstr);
  623. }
  624. Variant socket_server_impl(const Util::HostURL &hosturl,
  625. int flags, /* = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN */
  626. VRefParam errnum /* = null */,
  627. VRefParam errstr /* = null */) {
  628. Resource ret;
  629. Socket *sock = NULL;
  630. if (!create_new_socket(hosturl, errnum, errstr, ret, sock, 0.0)) {
  631. return false;
  632. }
  633. assert(ret.get() && sock);
  634. sockaddr_storage sa_storage;
  635. struct sockaddr *sa_ptr;
  636. size_t sa_size;
  637. if (!set_sockaddr(sa_storage, sock, hosturl.getHost().c_str(),
  638. hosturl.getPort(), sa_ptr, sa_size)) {
  639. return false;
  640. }
  641. int yes = 1;
  642. setsockopt(sock->fd(), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
  643. if ((flags & k_STREAM_SERVER_BIND) != 0 &&
  644. ::bind(sock->fd(), sa_ptr, sa_size) < 0) {
  645. SOCKET_ERROR(sock, "unable to bind to given address", errno);
  646. return false;
  647. }
  648. if ((flags & k_STREAM_SERVER_LISTEN) != 0 && listen(sock->fd(), 128) < 0) {
  649. SOCKET_ERROR(sock, "unable to listen on socket", errno);
  650. return false;
  651. }
  652. return ret;
  653. }
  654. Variant f_socket_accept(CResRef socket) {
  655. Socket *sock = socket.getTyped<Socket>();
  656. struct sockaddr sa;
  657. socklen_t salen = sizeof(sa);
  658. Socket *new_sock = new Socket(accept(sock->fd(), &sa, &salen),
  659. sock->getType());
  660. if (!new_sock->valid()) {
  661. SOCKET_ERROR(new_sock, "unable to accept incoming connection", errno);
  662. delete new_sock;
  663. return false;
  664. }
  665. return Resource(new_sock);
  666. }
  667. Variant f_socket_read(CResRef socket, int length, int type /* = 0 */) {
  668. if (length <= 0) {
  669. return false;
  670. }
  671. Socket *sock = socket.getTyped<Socket>();
  672. char *tmpbuf = (char *)malloc(length + 1);
  673. int retval;
  674. if (type == PHP_NORMAL_READ) {
  675. retval = php_read(sock, tmpbuf, length, 0);
  676. } else {
  677. retval = recv(sock->fd(), tmpbuf, length, 0);
  678. }
  679. if (retval == -1) {
  680. /* if the socket is in non-blocking mode and there's no data to read,
  681. don't output any error, as this is a normal situation, and not an error */
  682. if (errno == EAGAIN || errno == EWOULDBLOCK) {
  683. sock->setError(errno);
  684. } else {
  685. SOCKET_ERROR(sock, "unable to read from socket", errno);
  686. }
  687. free(tmpbuf);
  688. return false;
  689. }
  690. tmpbuf[retval] = '\0' ;
  691. return String(tmpbuf, retval, AttachString);
  692. }
  693. Variant f_socket_write(CResRef socket, const String& buffer, int length /* = 0 */) {
  694. Socket *sock = socket.getTyped<Socket>();
  695. if (length == 0 || length > buffer.size()) {
  696. length = buffer.size();
  697. }
  698. int retval = write(sock->fd(), buffer.data(), length);
  699. if (retval < 0) {
  700. SOCKET_ERROR(sock, "unable to write to socket", errno);
  701. return false;
  702. }
  703. return retval;
  704. }
  705. Variant f_socket_send(CResRef socket, const String& buf, int len, int flags) {
  706. Socket *sock = socket.getTyped<Socket>();
  707. if (len > buf.size()) {
  708. len = buf.size();
  709. }
  710. int retval = send(sock->fd(), buf.data(), len, flags);
  711. if (retval == -1) {
  712. SOCKET_ERROR(sock, "unable to write to socket", errno);
  713. return false;
  714. }
  715. return retval;
  716. }
  717. Variant f_socket_sendto(CResRef socket, const String& buf, int len, int flags,
  718. const String& addr, int port /* = -1 */) {
  719. Socket *sock = socket.getTyped<Socket>();
  720. if (len > buf.size()) {
  721. len = buf.size();
  722. }
  723. int retval;
  724. switch (sock->getType()) {
  725. case AF_UNIX:
  726. {
  727. struct sockaddr_un s_un;
  728. memset(&s_un, 0, sizeof(s_un));
  729. s_un.sun_family = AF_UNIX;
  730. snprintf(s_un.sun_path, 108, "%s", addr.data());
  731. retval = sendto(sock->fd(), buf.data(), len, flags,
  732. (struct sockaddr *)&s_un, SUN_LEN(&s_un));
  733. }
  734. break;
  735. case AF_INET:
  736. {
  737. if (port == -1) {
  738. throw_missing_arguments_nr("socket_sendto", 6, 5);
  739. return false;
  740. }
  741. struct sockaddr_in sin;
  742. memset(&sin, 0, sizeof(sin));
  743. sin.sin_family = AF_INET;
  744. sin.sin_port = htons((unsigned short) port);
  745. if (!php_set_inet_addr(&sin, addr.c_str(), sock)) {
  746. return false;
  747. }
  748. retval = sendto(sock->fd(), buf.data(), len, flags,
  749. (struct sockaddr *)&sin, sizeof(sin));
  750. }
  751. break;
  752. case AF_INET6:
  753. {
  754. if (port == -1) {
  755. throw_missing_arguments_nr("socket_sendto", 6, 5);
  756. return false;
  757. }
  758. struct sockaddr_in6 sin6;
  759. memset(&sin6, 0, sizeof(sin6));
  760. sin6.sin6_family = AF_INET6;
  761. sin6.sin6_port = htons((unsigned short) port);
  762. if (!php_set_inet6_addr(&sin6, addr.c_str(), sock)) {
  763. return false;
  764. }
  765. retval = sendto(sock->fd(), buf.data(), len, flags,
  766. (struct sockaddr *)&sin6, sizeof(sin6));
  767. }
  768. break;
  769. default:
  770. raise_warning("Unsupported socket type %d", sock->getType());
  771. return false;
  772. }
  773. if (retval == -1) {
  774. SOCKET_ERROR(sock, "unable to write to socket", errno);
  775. return false;
  776. }
  777. return retval;
  778. }
  779. Variant f_socket_recv(CResRef socket, VRefParam buf, int len, int flags) {
  780. if (len <= 0) {
  781. return false;
  782. }
  783. Socket *sock = socket.getTyped<Socket>();
  784. char *recv_buf = (char *)malloc(len + 1);
  785. int retval;
  786. if ((retval = recv(sock->fd(), recv_buf, len, flags)) < 1) {
  787. free(recv_buf);
  788. buf = uninit_null();
  789. } else {
  790. recv_buf[retval] = '\0';
  791. buf = String(recv_buf, retval, AttachString);
  792. }
  793. if (retval == -1) {
  794. SOCKET_ERROR(sock, "unable to read from socket", errno);
  795. return false;
  796. }
  797. return retval;
  798. }
  799. const StaticString
  800. s_2colons("::"),
  801. s_0_0_0_0("0.0.0.0");
  802. Variant f_socket_recvfrom(CResRef socket, VRefParam buf, int len, int flags,
  803. VRefParam name, VRefParam port /* = -1*/) {
  804. if (len <= 0) {
  805. return false;
  806. }
  807. Socket *sock = socket.getTyped<Socket>();
  808. char *recv_buf = (char *)malloc(len + 2);
  809. socklen_t slen;
  810. int retval;
  811. switch (sock->getType()) {
  812. case AF_UNIX:
  813. {
  814. struct sockaddr_un s_un;
  815. slen = sizeof(s_un);
  816. memset(&s_un, 0, slen);
  817. s_un.sun_family = AF_UNIX;
  818. retval = recvfrom(sock->fd(), recv_buf, len, flags,
  819. (struct sockaddr *)&s_un, (socklen_t *)&slen);
  820. if (retval < 0) {
  821. free(recv_buf);
  822. SOCKET_ERROR(sock, "unable to recvfrom", errno);
  823. return false;
  824. }
  825. recv_buf[retval] = 0;
  826. buf = String(recv_buf, retval, AttachString);
  827. name = String(s_un.sun_path, CopyString);
  828. }
  829. break;
  830. case AF_INET:
  831. {
  832. if (int(port) == -1) {
  833. throw_missing_arguments_nr("socket_recvfrom", 5, 4);
  834. return false;
  835. }
  836. struct sockaddr_in sin;
  837. slen = sizeof(sin);
  838. memset(&sin, 0, slen);
  839. retval = recvfrom(sock->fd(), recv_buf, len, flags,
  840. (struct sockaddr *)&sin, (socklen_t *)&slen);
  841. if (retval < 0) {
  842. free(recv_buf);
  843. SOCKET_ERROR(sock, "unable to recvfrom", errno);
  844. return false;
  845. }
  846. recv_buf[retval] = 0;
  847. buf = String(recv_buf, retval, AttachString);
  848. name = String(Util::safe_inet_ntoa(sin.sin_addr));
  849. if (name.toString().empty()) {
  850. name = s_0_0_0_0;
  851. }
  852. port = ntohs(sin.sin_port);
  853. }
  854. break;
  855. case AF_INET6:
  856. {
  857. if (int(port) == -1) {
  858. throw_missing_arguments_nr("socket_recvfrom", 5, 4);
  859. return false;
  860. }
  861. struct sockaddr_in6 sin6;
  862. slen = sizeof(sin6);
  863. memset(&sin6, 0, slen);
  864. retval = recvfrom(sock->fd(), recv_buf, len, flags,
  865. (struct sockaddr *)&sin6, (socklen_t *)&slen);
  866. if (retval < 0) {
  867. free(recv_buf);
  868. SOCKET_ERROR(sock, "unable to recvfrom", errno);
  869. return false;
  870. }
  871. char addr6[INET6_ADDRSTRLEN];
  872. const char* succ =
  873. inet_ntop(AF_INET6, &sin6.sin6_addr, addr6, INET6_ADDRSTRLEN);
  874. recv_buf[retval] = 0;
  875. buf = String(recv_buf, retval, AttachString);
  876. if (succ) {
  877. name = String(addr6, CopyString);
  878. } else {
  879. name = s_2colons;
  880. }
  881. port = ntohs(sin6.sin6_port);
  882. }
  883. break;
  884. default:
  885. raise_warning("Unsupported socket type %d", sock->getType());
  886. return false;
  887. }
  888. return retval;
  889. }
  890. bool f_socket_shutdown(CResRef socket, int how /* = 0 */) {
  891. Socket *sock = socket.getTyped<Socket>();
  892. if (shutdown(sock->fd(), how) != 0) {
  893. SOCKET_ERROR(sock, "unable to shutdown socket", errno);
  894. return false;
  895. }
  896. return true;
  897. }
  898. void f_socket_close(CResRef socket) {
  899. Socket *sock = socket.getTyped<Socket>();
  900. sock->close();
  901. }
  902. String f_socket_strerror(int errnum) {
  903. return String(folly::errnoStr(errnum).toStdString());
  904. }
  905. int64_t f_socket_last_error(CResRef socket /* = null_object */) {
  906. if (!socket.isNull()) {
  907. Socket *sock = socket.getTyped<Socket>();
  908. return sock->getError();
  909. }
  910. return Socket::getLastError();
  911. }
  912. void f_socket_clear_error(CResRef socket /* = null_object */) {
  913. if (!socket.isNull()) {
  914. Socket *sock = socket.getTyped<Socket>();
  915. sock->setError(0);
  916. }
  917. }
  918. ///////////////////////////////////////////////////////////////////////////////
  919. // fsock: treating sockets as "file"
  920. Variant sockopen_impl(const Util::HostURL &hosturl, VRefParam errnum,
  921. VRefParam errstr, double timeout, bool persistent) {
  922. string key;
  923. if (persistent) {
  924. key = hosturl.getHostURL();
  925. Socket *sock =
  926. dynamic_cast<Socket*>(g_persistentObjects->get("socket", key.c_str()));
  927. if (sock) {
  928. if (sock->getError() == 0 && sock->checkLiveness()) {
  929. return Resource(sock);
  930. }
  931. // socket had an error earlier, we need to remove it from persistent
  932. // storage, and create a new one
  933. g_persistentObjects->remove("socket", key.c_str());
  934. }
  935. }
  936. Resource ret;
  937. Socket *sock = NULL;
  938. if (timeout < 0) timeout = RuntimeOption::SocketDefaultTimeout;
  939. // test if protocol is SSL
  940. SSLSocket *sslsock = SSLSocket::Create(hosturl, timeout);
  941. if (sslsock) {
  942. sock = sslsock;
  943. ret = sock;
  944. } else if (!create_new_socket(hosturl, errnum, errstr, ret, sock, timeout)) {
  945. return false;
  946. }
  947. assert(ret.get() && sock);
  948. sockaddr_storage sa_storage;
  949. struct sockaddr *sa_ptr;
  950. size_t sa_size;
  951. if (!set_sockaddr(sa_storage, sock, hosturl.getHost().c_str(),
  952. hosturl.getPort(), sa_ptr, sa_size)) {
  953. return false;
  954. }
  955. int retval;
  956. int fd = sock->fd();
  957. IOStatusHelper io("socket::connect",
  958. hosturl.getHostURL().c_str(), hosturl.getPort());
  959. if (timeout <= 0) {
  960. retval = connect(fd, sa_ptr, sa_size);
  961. } else {
  962. // set non-blocking so we can do timeouts
  963. long arg = fcntl(fd, F_GETFL, NULL);
  964. fcntl(fd, F_SETFL, arg | O_NONBLOCK);
  965. retval = connect(fd, sa_ptr, sa_size);
  966. if (retval < 0) {
  967. if (errno == EINPROGRESS) {
  968. struct pollfd fds[1];
  969. fds[0].fd = fd;
  970. fds[0].events = POLLOUT;
  971. if (poll(fds, 1, (int)(timeout * 1000))) {
  972. socklen_t lon = sizeof(int);
  973. int valopt;
  974. getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
  975. if (valopt) {
  976. std::string msg = "failed to connect to " + hosturl.getHostURL();
  977. SOCKET_ERROR(sock, msg.c_str(), valopt);
  978. errnum = sock->getError();
  979. errstr = String(folly::errnoStr(sock->getError()).toStdString());
  980. return false;
  981. } else {
  982. retval = 0; // success
  983. }
  984. } else {
  985. std::string msg = "timed out after ";
  986. msg += boost::lexical_cast<std::string>(timeout);
  987. msg += " seconds when connecting to " + hosturl.getHostURL();
  988. SOCKET_ERROR(sock, msg.c_str(), ETIMEDOUT);
  989. errnum = sock->getError();
  990. errstr = String(folly::errnoStr(sock->getError()).toStdString());
  991. return false;
  992. }
  993. }
  994. }
  995. // set to blocking mode
  996. arg = fcntl(fd, F_GETFL, NULL);
  997. fcntl(fd, F_SETFL, arg & ~O_NONBLOCK);
  998. }
  999. if (retval != 0) {
  1000. errnum = sock->getError();
  1001. errstr = String(folly::errnoStr(sock->getError()).toStdString());
  1002. return false;
  1003. }
  1004. if (sslsock && !sslsock->onConnect()) {
  1005. raise_warning("Failed to enable crypto");
  1006. return false;
  1007. }
  1008. if (persistent) {
  1009. assert(!key.empty());
  1010. g_persistentObjects->set("socket", key.c_str(), sock);
  1011. }
  1012. return ret;
  1013. }
  1014. Variant f_fsockopen(const String& hostname, int port /* = -1 */,
  1015. VRefParam errnum /* = null */,
  1016. VRefParam errstr /* = null */,
  1017. double timeout /* = -1.0 */) {
  1018. Util::HostURL hosturl(static_cast<const std::string>(hostname), port);
  1019. return sockopen_impl(hosturl, errnum, errstr, timeout, false);
  1020. }
  1021. Variant f_pfsockopen(const String& hostname, int port /* = -1 */,
  1022. VRefParam errnum /* = null */,
  1023. VRefParam errstr /* = null */,
  1024. double timeout /* = -1.0 */) {
  1025. // TODO: persistent socket handling
  1026. Util::HostURL hosturl(static_cast<const std::string>(hostname), port);
  1027. return sockopen_impl(hosturl, errnum, errstr, timeout, true);
  1028. }
  1029. String ipaddr_convert(struct sockaddr *addr, int addrlen) {
  1030. char buffer[NI_MAXHOST];
  1031. int error = getnameinfo(addr, addrlen, buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST);
  1032. if (error) {
  1033. raise_warning("%s", gai_strerror(error));
  1034. return "";
  1035. }
  1036. return String(buffer, CopyString);
  1037. }
  1038. const StaticString
  1039. s_family("family"),
  1040. s_socktype("socktype"),
  1041. s_protocol("protocol"),
  1042. s_address("address"),
  1043. s_port("port"),
  1044. s_flow_info("flow_info"),
  1045. s_scope_id("scope_id"),
  1046. s_sockaddr("sockaddr");
  1047. Variant f_getaddrinfo(const String& host, const String& port, int family /* = 0 */,
  1048. int socktype /* = 0 */, int protocol /* = 0 */,
  1049. int flags /* = 0 */) {
  1050. const char *hptr = NULL, *pptr = NULL;
  1051. if (!host.empty()) {
  1052. hptr = host.c_str();
  1053. }
  1054. if (!port.empty()) {
  1055. pptr = port.c_str();
  1056. }
  1057. struct addrinfo hints, *res;
  1058. struct addrinfo *res0 = NULL;
  1059. int error;
  1060. memset(&hints, 0, sizeof(hints));
  1061. hints.ai_family = family;
  1062. hints.ai_socktype = socktype;
  1063. hints.ai_protocol = protocol;
  1064. hints.ai_flags = flags;
  1065. error = getaddrinfo(hptr, pptr, &hints, &res0);
  1066. if (error) {
  1067. raise_warning("%s", gai_strerror(error));
  1068. if (res0) {
  1069. freeaddrinfo(res0);
  1070. }
  1071. return false;
  1072. }
  1073. Array ret = Array::Create();
  1074. for (res = res0; res; res = res->ai_next) {
  1075. Array data = Array::Create();
  1076. Array sockinfo = Array::Create();
  1077. data.set(s_family, res->ai_family);
  1078. data.set(s_socktype, res->ai_socktype);
  1079. data.set(s_protocol, res->ai_protocol);
  1080. switch (res->ai_addr->sa_family) {
  1081. case AF_INET:
  1082. {
  1083. struct sockaddr_in *a;
  1084. String buffer = ipaddr_convert(res->ai_addr, sizeof(*a));
  1085. if (!buffer.empty()) {
  1086. a = (struct sockaddr_in *)res->ai_addr;
  1087. sockinfo.set(s_address, buffer);
  1088. sockinfo.set(s_port, ntohs(a->sin_port));
  1089. }
  1090. break;
  1091. }
  1092. case AF_INET6:
  1093. {
  1094. struct sockaddr_in6 *a;
  1095. String buffer = ipaddr_convert(res->ai_addr, sizeof(*a));
  1096. if (!buffer.empty()) {
  1097. a = (struct sockaddr_in6 *)res->ai_addr;
  1098. sockinfo.set(s_address, buffer);
  1099. sockinfo.set(s_port, ntohs(a->sin6_port));
  1100. sockinfo.set(s_flow_info, (int32_t)a->sin6_flowinfo);
  1101. sockinfo.set(s_scope_id, (int32_t)a->sin6_scope_id);
  1102. }
  1103. break;
  1104. }
  1105. }
  1106. data.set(s_sockaddr, (sockinfo.empty() ? nullptr : sockinfo));
  1107. ret.append(data);
  1108. }
  1109. if (res0) {
  1110. freeaddrinfo(res0);
  1111. }
  1112. return ret;
  1113. }
  1114. ///////////////////////////////////////////////////////////////////////////////
  1115. }