void php_yar_error_ex(yar_response_t *response, int type TSRMLS_DC, const char *format, va_list args) /* {{{ */ { char *msg; uint len; len = vspprintf(&msg, 0, format, args); php_yar_response_set_error(response, type, msg, len TSRMLS_CC); /* intentionally missed efree(msg); */ return; } /* }}} */
yar_response_t * php_yar_socket_exec(yar_transport_interface_t* self, yar_request_t *request) /* {{{ */ { fd_set rfds; struct timeval tv; yar_header_t *header; yar_response_t *response; int fd, retval, recvd; size_t len = 0, total_recvd = 0; char *msg, buf[RECV_BUF_SIZE], *payload = NULL; yar_socket_data_t *data = (yar_socket_data_t *)self->data; response = ecalloc(1, sizeof(yar_response_t)); FD_ZERO(&rfds); if (SUCCESS == php_stream_cast(data->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&fd, 1) && fd >= 0) { PHP_SAFE_FD_SET(fd, &rfds); } else { len = snprintf(buf, sizeof(buf), "Unable cast socket fd form stream (%s)", strerror(errno)); php_yar_response_set_error(response, YAR_ERR_TRANSPORT, buf, len); return response; } tv.tv_sec = (ulong)(YAR_G(timeout) / 1000); tv.tv_usec = (ulong)((YAR_G(timeout) % 1000)? (YAR_G(timeout) & 1000) * 1000 : 0); wait_io: retval = php_select(fd+1, &rfds, NULL, NULL, &tv); if (retval == -1) { len = snprintf(buf, sizeof(buf), "Unable to select %d '%s'", fd, strerror(errno)); php_yar_response_set_error(response, YAR_ERR_TRANSPORT, buf, len); return response; } else if (retval == 0) { len = snprintf(buf, sizeof(buf), "select timeout %ldms reached", YAR_G(timeout)); php_yar_response_set_error(response, YAR_ERR_TRANSPORT, buf, len); return response; } if (PHP_SAFE_FD_ISSET(fd, &rfds)) { zval *retval, rret; if (!payload) { if ((recvd = php_stream_xport_recvfrom(data->stream, buf, sizeof(buf), 0, NULL, NULL, NULL)) > 0) { if (!(header = php_yar_protocol_parse(buf))) { php_yar_error(response, YAR_ERR_PROTOCOL, "malformed response header '%.32s'", payload); return response; } payload = emalloc(header->body_len); len = header->body_len; total_recvd = recvd - sizeof(yar_header_t); memcpy(payload, buf + sizeof(yar_header_t), total_recvd); if (recvd < (sizeof(yar_header_t) + len)) { goto wait_io; } } else if (recvd < 0) { /* this should never happen */ goto wait_io; } } else { if ((recvd = php_stream_xport_recvfrom(data->stream, payload + total_recvd, len - total_recvd, 0, NULL, NULL, NULL)) > 0) { total_recvd += recvd; } if (total_recvd < len) { goto wait_io; } } if (len) { if (!(retval = php_yar_packager_unpack(payload, len, &msg, &rret))) { php_yar_response_set_error(response, YAR_ERR_PACKAGER, msg, strlen(msg)); efree(msg); return response; } php_yar_response_map_retval(response, retval); DEBUG_C(ZEND_ULONG_FMT": server response content packaged by '%.*s', len '%ld', content '%.32s'", response->id, 7, payload, header->body_len, payload + 8); efree(payload); zval_ptr_dtor(retval); } else { php_yar_response_set_error(response, YAR_ERR_EMPTY_RESPONSE, ZEND_STRL("empty response")); } return response; } else { goto wait_io; } } /* }}} */