/util/response.c

https://bitbucket.org/lingfeng_xiang/php-ext-handlersocketi · C · 588 lines · 476 code · 112 blank · 0 comment · 184 complexity · 4d34356cf37d079acc3595300439af49 MD5 · raw file

  1. #include "php.h"
  2. #include "php_network.h"
  3. #include "ext/standard/php_smart_str.h"
  4. #include "common.h"
  5. #include "response.h"
  6. #define HS_SOCKET_BLOCK_SIZE 4096
  7. #ifndef PHP_WIN32
  8. #define php_select(m, r, w, e, t) select(m, r, w, e, t)
  9. #else
  10. #include "win32/select.h"
  11. #endif
  12. static inline long
  13. hs_response_select(php_stream *stream, long timeout TSRMLS_DC)
  14. {
  15. php_socket_t max_fd = 0;
  16. int retval, max_set_count = 0;
  17. struct timeval tv;
  18. struct timeval *tv_p = NULL;
  19. fd_set fds;
  20. FD_ZERO(&fds);
  21. if (php_stream_cast(stream,
  22. PHP_STREAM_AS_FD_FOR_SELECT|PHP_STREAM_CAST_INTERNAL,
  23. (void*)&max_fd, 1) == SUCCESS && max_fd != -1) {
  24. PHP_SAFE_FD_SET(max_fd, &fds);
  25. max_set_count++;
  26. }
  27. PHP_SAFE_MAX_FD(max_fd, max_set_count);
  28. if (timeout > 0) {
  29. tv.tv_sec = timeout;
  30. tv.tv_usec = 0;
  31. tv_p = &tv;
  32. }
  33. retval = php_select(max_fd+1, &fds, NULL, NULL, tv_p);
  34. if (retval == -1) {
  35. zend_error(E_WARNING, "[HandlerSocket] unable to select");
  36. return -1;
  37. }
  38. if (!PHP_SAFE_FD_ISSET(max_fd, &fds)) {
  39. return -1;
  40. }
  41. return 0;
  42. }
  43. static inline long
  44. hs_response_recv(php_stream *stream, char *recv, size_t size TSRMLS_DC)
  45. {
  46. long ret;
  47. #ifdef HS_DEBUG
  48. long i;
  49. smart_str debug = {0};
  50. #endif
  51. ret = php_stream_read(stream, recv, size);
  52. if (ret <= 0) {
  53. return -1;
  54. }
  55. #ifdef HS_DEBUG
  56. for (i = 0; i < ret; i++) {
  57. if ((unsigned char)recv[i] == HS_CODE_NULL) {
  58. smart_str_appendl_ex(&debug, "\\0", strlen("\\0"), 1);
  59. } else {
  60. smart_str_appendc(&debug, recv[i]);
  61. }
  62. }
  63. smart_str_0(&debug);
  64. php_printf("[handlersocket] (recv) %ld : \"%s\"", ret, debug.c);
  65. smart_str_free(&debug);
  66. #endif
  67. return ret;
  68. }
  69. static inline zval
  70. *hs_response_add(zval *return_value TSRMLS_DC)
  71. {
  72. zval *value;
  73. MAKE_STD_ZVAL(value);
  74. array_init(value);
  75. add_next_index_zval(return_value, value);
  76. return value;
  77. }
  78. static inline zval
  79. *hs_response_zval(smart_str *buf TSRMLS_DC)
  80. {
  81. zval *val;
  82. MAKE_STD_ZVAL(val);
  83. ZVAL_STRINGL(val, buf->c, buf->len, 1);
  84. return val;
  85. }
  86. void
  87. hs_response_value(php_stream *stream, long timeout, zval *return_value,
  88. zval *error, int modify TSRMLS_DC)
  89. {
  90. char *recv;
  91. long i, j, len;
  92. zval *val, *item;
  93. smart_str response = {0};
  94. long n = 0, block_size = HS_SOCKET_BLOCK_SIZE;
  95. int escape = 0, flag = 0, null = 0;
  96. long ret[2] = {-1, -1};
  97. if (hs_response_select(stream, timeout TSRMLS_CC) < 0) {
  98. ZVAL_BOOL(return_value, 0);
  99. }
  100. recv = emalloc(block_size+1);
  101. len = hs_response_recv(stream, recv, block_size TSRMLS_CC);
  102. if (len <= 0) {
  103. efree(recv);
  104. ZVAL_BOOL(return_value, 0);
  105. return;
  106. }
  107. do {
  108. for (i = 0; i < len; i++) {
  109. if (recv[i] == HS_CODE_DELIMITER || recv[i] == HS_CODE_EOL) {
  110. val = hs_response_zval(&response TSRMLS_CC);
  111. convert_to_long(val);
  112. ret[flag] = Z_LVAL_P(val);
  113. flag++;
  114. zval_ptr_dtor(&val);
  115. smart_str_free(&response);
  116. } else {
  117. smart_str_appendc(&response, recv[i]);
  118. }
  119. if (flag > 1) {
  120. break;
  121. }
  122. }
  123. if (flag > 1) {
  124. break;
  125. } else {
  126. i = 0;
  127. len = hs_response_recv(stream, recv, block_size TSRMLS_CC);
  128. if (len <= 0) {
  129. break;
  130. }
  131. }
  132. } while (1);
  133. if (ret[0] != 0) {
  134. if (recv[i] != HS_CODE_EOL) {
  135. smart_str err = {0};
  136. i++;
  137. if (i > len) {
  138. i = 0;
  139. len = -1;
  140. }
  141. do {
  142. for (j = i; j < len; j++) {
  143. if (recv[j] == HS_CODE_EOL) {
  144. break;
  145. }
  146. if (recv[j] == HS_CODE_ESCAPE_PREFIX) {
  147. escape = 1;
  148. } else if (escape) {
  149. escape = 0;
  150. smart_str_appendc(
  151. &err, (unsigned char)recv[j]-HS_CODE_ESCAPE_ADD);
  152. } else {
  153. smart_str_appendc(&err, recv[j]);
  154. }
  155. }
  156. if (recv[j] == HS_CODE_EOL) {
  157. break;
  158. }
  159. i = 0;
  160. } while ((len = hs_response_recv(
  161. stream, recv, block_size TSRMLS_CC)) > 0);
  162. if (error) {
  163. ZVAL_STRINGL(error, err.c, err.len, 1);
  164. }
  165. smart_str_free(&err);
  166. } else if (error) {
  167. ZVAL_NULL(error);
  168. }
  169. efree(recv);
  170. ZVAL_BOOL(return_value, 0);
  171. return;
  172. }
  173. if (ret[1] == 1 && recv[i] == HS_CODE_EOL) {
  174. efree(recv);
  175. ZVAL_BOOL(return_value, 1);
  176. return;
  177. }
  178. i++;
  179. if (i > len) {
  180. i = 0;
  181. len = -1;
  182. }
  183. if (modify) {
  184. if (i > 0 && recv[i-1] == HS_CODE_EOL) {
  185. efree(recv);
  186. ZVAL_LONG(return_value, 0);
  187. return;
  188. }
  189. do {
  190. for (j = i; j < len; j++) {
  191. if (recv[j] == HS_CODE_EOL) {
  192. ZVAL_STRINGL(return_value, response.c, response.len, 1);
  193. break;
  194. }
  195. if (recv[j] == HS_CODE_ESCAPE_PREFIX) {
  196. escape = 1;
  197. } else if (escape) {
  198. escape = 0;
  199. smart_str_appendc(
  200. &response, (unsigned char)recv[j]-HS_CODE_ESCAPE_ADD);
  201. } else {
  202. smart_str_appendc(&response, recv[j]);
  203. }
  204. }
  205. if (recv[j] == HS_CODE_EOL) {
  206. break;
  207. }
  208. i = 0;
  209. } while ((len = hs_response_recv(
  210. stream, recv, block_size TSRMLS_CC)) > 0);
  211. convert_to_long(return_value);
  212. } else {
  213. array_init(return_value);
  214. if (i > 0 && recv[i-1] == HS_CODE_EOL) {
  215. efree(recv);
  216. return;
  217. }
  218. item = hs_response_add(return_value TSRMLS_CC);
  219. do {
  220. for (j = i; j < len; j++) {
  221. if (recv[j] == HS_CODE_DELIMITER) {
  222. if (response.len == 0 && null == 1) {
  223. add_next_index_null(item);
  224. } else {
  225. add_next_index_stringl(item, response.c,
  226. response.len, 1);
  227. }
  228. n++;
  229. null = 0;
  230. if (n == ret[1]) {
  231. item = hs_response_add(return_value TSRMLS_CC);
  232. n = 0;
  233. }
  234. smart_str_free(&response);
  235. continue;
  236. } else if (recv[j] == HS_CODE_EOL) {
  237. if (response.len == 0 && null == 1) {
  238. add_next_index_null(item);
  239. } else {
  240. add_next_index_stringl(item, response.c,
  241. response.len, 1);
  242. }
  243. null = 0;
  244. break;
  245. }
  246. if (recv[j] == HS_CODE_ESCAPE_PREFIX) {
  247. escape = 1;
  248. } else if (escape) {
  249. escape = 0;
  250. smart_str_appendc(
  251. &response, (unsigned char)recv[j]-HS_CODE_ESCAPE_ADD);
  252. } else if (recv[j] == HS_CODE_NULL) {
  253. null = 1;
  254. } else {
  255. smart_str_appendc(&response, recv[j]);
  256. }
  257. }
  258. if (recv[j] == HS_CODE_EOL) {
  259. break;
  260. }
  261. i = 0;
  262. } while ((len = hs_response_recv(
  263. stream, recv, block_size TSRMLS_CC)) > 0);
  264. }
  265. efree(recv);
  266. smart_str_free(&response);
  267. }
  268. void
  269. hs_response_multi(php_stream *stream, long timeout, zval *return_value,
  270. zval *error, zval *mreq TSRMLS_DC)
  271. {
  272. char *recv;
  273. long i, len, count;
  274. long current = 0;
  275. smart_str response = {0};
  276. long block_size = HS_SOCKET_BLOCK_SIZE;
  277. if (hs_response_select(stream, timeout TSRMLS_CC) < 0) {
  278. ZVAL_BOOL(return_value, 0);
  279. }
  280. recv = emalloc(block_size+1);
  281. len = hs_response_recv(stream, recv, block_size TSRMLS_CC);
  282. if (len <= 0) {
  283. efree(recv);
  284. RETVAL_BOOL(0);
  285. }
  286. count = zend_hash_num_elements(HASH_OF(mreq));
  287. array_init(return_value);
  288. array_init(error);
  289. for(i = 0; i < count; i++) {
  290. long j, k;
  291. zval *rval, *item, *val, **tmp;
  292. int flag = 0, escape = 0, null = 0;
  293. long n = 0, modify = 0;
  294. long ret[2] = {-1, -1};
  295. if (zend_hash_index_find(HASH_OF(mreq), i, (void **)&tmp) == SUCCESS) {
  296. modify = Z_LVAL_PP(tmp);
  297. }
  298. smart_str_free(&response);
  299. do {
  300. for (j = current; j < len; j++) {
  301. if (recv[j] == HS_CODE_DELIMITER || recv[j] == HS_CODE_EOL) {
  302. rval = hs_response_zval(&response TSRMLS_CC);
  303. convert_to_long(rval);
  304. ret[flag] = Z_LVAL_P(rval);
  305. flag++;
  306. zval_ptr_dtor(&rval);
  307. smart_str_free(&response);
  308. } else {
  309. smart_str_appendc(&response, recv[j]);
  310. }
  311. if (flag > 1) {
  312. break;
  313. }
  314. }
  315. if (flag > 1) {
  316. break;
  317. } else {
  318. j = 0;
  319. current = 0;
  320. len = hs_response_recv(stream, recv, block_size TSRMLS_CC);
  321. if (len <= 0) {
  322. break;
  323. }
  324. }
  325. } while (1);
  326. if (ret[0] != 0) {
  327. if (recv[j] != HS_CODE_EOL) {
  328. smart_str err = {0};
  329. j++;
  330. if (j > len) {
  331. j = 0;
  332. current = 0;
  333. len = -1;
  334. }
  335. do {
  336. for (k = j; k < len; k++) {
  337. if (recv[k] == HS_CODE_EOL) {
  338. break;
  339. }
  340. if (recv[k] == HS_CODE_ESCAPE_PREFIX) {
  341. escape = 1;
  342. } else if (escape) {
  343. escape = 0;
  344. smart_str_appendc(
  345. &err,
  346. (unsigned char)recv[k] - HS_CODE_ESCAPE_ADD);
  347. } else {
  348. smart_str_appendc(&err, recv[k]);
  349. }
  350. }
  351. if (recv[k] == HS_CODE_EOL) {
  352. current = k;
  353. break;
  354. }
  355. j = 0;
  356. current = 0;
  357. } while ((len = hs_response_recv(
  358. stream, recv, block_size TSRMLS_CC)) > 0);
  359. add_next_index_stringl(error, err.c, err.len, 1);
  360. smart_str_free(&err);
  361. } else {
  362. add_next_index_null(error);
  363. }
  364. add_next_index_bool(return_value, 0);
  365. current++;
  366. continue;
  367. }
  368. add_next_index_null(error);
  369. if (ret[1] == 1 && recv[j] == HS_CODE_EOL) {
  370. add_next_index_bool(return_value, 1);
  371. current = j + 1;
  372. continue;
  373. }
  374. j++;
  375. if (j > len) {
  376. j = 0;
  377. current = 0;
  378. len = -1;
  379. }
  380. if (modify) {
  381. zval *num_z;
  382. if (j > 0 && recv[j-1] == HS_CODE_EOL) {
  383. current = j;
  384. add_next_index_long(return_value, 0);
  385. continue;
  386. }
  387. MAKE_STD_ZVAL(num_z);
  388. do {
  389. for (k = j; k < len; k++) {
  390. if (recv[k] == HS_CODE_EOL) {
  391. ZVAL_STRINGL(num_z, response.c, response.len, 1);
  392. break;
  393. }
  394. if (recv[k] == HS_CODE_ESCAPE_PREFIX) {
  395. escape = 1;
  396. } else if (escape) {
  397. escape = 0;
  398. smart_str_appendc(
  399. &response,
  400. (unsigned char)recv[k] - HS_CODE_ESCAPE_ADD);
  401. } else {
  402. smart_str_appendc(&response, recv[k]);
  403. }
  404. }
  405. if (recv[k] == HS_CODE_EOL) {
  406. current = k;
  407. break;
  408. }
  409. j = 0;
  410. current = 0;
  411. } while ((len = hs_response_recv(
  412. stream, recv, block_size TSRMLS_CC)) > 0);
  413. convert_to_long(num_z);
  414. add_next_index_long(return_value, Z_LVAL_P(num_z));
  415. zval_ptr_dtor(&num_z);
  416. } else {
  417. item = hs_response_add(return_value TSRMLS_CC);
  418. if (j > 0 && recv[j-1] == HS_CODE_EOL) {
  419. current = j;
  420. continue;
  421. }
  422. val = hs_response_add(item TSRMLS_CC);
  423. do {
  424. for (k = j; k < len; k++) {
  425. if (recv[k] == HS_CODE_DELIMITER) {
  426. if (response.len == 0 && null == 1) {
  427. add_next_index_null(val);
  428. } else {
  429. add_next_index_stringl(val, response.c,
  430. response.len, 1);
  431. }
  432. null = 0;
  433. n++;
  434. if (n == ret[1]) {
  435. val = hs_response_add(item TSRMLS_CC);
  436. n = 0;
  437. }
  438. smart_str_free(&response);
  439. continue;
  440. } else if (recv[k] == HS_CODE_EOL) {
  441. if (response.len == 0 && null == 1) {
  442. add_next_index_null(val);
  443. } else {
  444. add_next_index_stringl(val, response.c,
  445. response.len, 1);
  446. }
  447. null = 0;
  448. break;
  449. }
  450. if (recv[k] == HS_CODE_ESCAPE_PREFIX) {
  451. escape = 1;
  452. } else if (escape) {
  453. escape = 0;
  454. smart_str_appendc(
  455. &response,
  456. (unsigned char)recv[k] - HS_CODE_ESCAPE_ADD);
  457. } else if (recv[k] == HS_CODE_NULL) {
  458. null = 1;
  459. } else {
  460. smart_str_appendc(&response, recv[k]);
  461. }
  462. }
  463. if (recv[k] == HS_CODE_EOL) {
  464. current = k;
  465. break;
  466. }
  467. j = 0;
  468. current = 0;
  469. } while ((len = hs_response_recv(
  470. stream, recv, block_size TSRMLS_CC)) > 0);
  471. }
  472. current++;
  473. }
  474. efree(recv);
  475. smart_str_free(&response);
  476. }