Пример #1
0
static inline long
hs_response_select(php_stream *stream, long timeout TSRMLS_DC)
{
    php_socket_t max_fd = 0;
    int retval, max_set_count = 0;
    struct timeval tv;
    struct timeval *tv_p = NULL;
    fd_set fds;

    FD_ZERO(&fds);

    if (php_stream_cast(stream,
                        PHP_STREAM_AS_FD_FOR_SELECT|PHP_STREAM_CAST_INTERNAL,
                        (void*)&max_fd, 1) == SUCCESS && max_fd != -1) {
        PHP_SAFE_FD_SET(max_fd, &fds);
        max_set_count++;
    }

    PHP_SAFE_MAX_FD(max_fd, max_set_count);

    if (timeout > 0) {
        tv.tv_sec = timeout;
        tv.tv_usec = 0;
        tv_p = &tv;
    }

    retval = php_select(max_fd+1, &fds, NULL, NULL, tv_p);
    if (retval == -1) {
        zend_error(E_WARNING, "[HandlerSocket] unable to select");
        return -1;
    }

    if (!PHP_SAFE_FD_ISSET(max_fd, &fds)) {
        return -1;
    }

    return 0;
}
Пример #2
0
int php_yar_socket_send(yar_transport_interface_t* self, yar_request_t *request, char **msg) /* {{{ */ {
	fd_set rfds;
	zend_string *payload;
	struct timeval tv;
	int ret = -1, fd, retval;
	char buf[SEND_BUF_SIZE];
	yar_header_t header = {0};
	yar_socket_data_t *data = (yar_socket_data_t *)self->data;

	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 {
		spprintf(msg, 0, "Unable cast socket fd form stream (%s)", strerror(errno));
		return 0;
	}

	if (!(payload = php_yar_request_pack(request, msg))) {
		return 0;
	}

	DEBUG_C(ZEND_ULONG_FMT": pack request by '%.*s', result len '%ld', content: '%.32s'", 
			request->id, 7, ZSTR_VAL(payload), ZSTR_LEN(payload), ZSTR_VAL(payload) + 8);

	/* for tcp/unix RPC, we need another way to supports auth */
	php_yar_protocol_render(&header, request->id, "Yar PHP Client", NULL, ZSTR_LEN(payload), data->persistent? YAR_PROTOCOL_PERSISTENT : 0);

	memcpy(buf, (char *)&header, sizeof(yar_header_t));

	tv.tv_sec = (ulong)(YAR_G(timeout) / 1000);
	tv.tv_usec = (ulong)((YAR_G(timeout) % 1000)? (YAR_G(timeout) & 1000) * 1000 : 0);

	retval = php_select(fd+1, NULL, &rfds, NULL, &tv);

	if (retval == -1) {
		zend_string_release(payload);
		spprintf(msg, 0, "select error '%s'", strerror(errno));
		return 0;
	} else if (retval == 0) {
		zend_string_release(payload);
		spprintf(msg, 0, "select timeout '%ld' seconds reached", YAR_G(timeout));
		return 0;
	}

	if (PHP_SAFE_FD_ISSET(fd, &rfds)) {
		size_t bytes_left = 0, bytes_sent = 0;

		if (ZSTR_LEN(payload) > (sizeof(buf) - sizeof(yar_header_t))) {
			memcpy(buf + sizeof(yar_header_t), ZSTR_VAL(payload), sizeof(buf) - sizeof(yar_header_t));
			if ((ret = php_stream_xport_sendto(data->stream, buf, sizeof(buf), 0, NULL, 0)) < 0) {
				zend_string_release(payload);
				spprintf(msg, 0, "unable to send data");
				return 0;
			}
		} else {
			memcpy(buf + sizeof(yar_header_t), ZSTR_VAL(payload), ZSTR_LEN(payload));
			if ((ret = php_stream_xport_sendto(data->stream, buf, sizeof(yar_header_t) + ZSTR_LEN(payload), 0, NULL, 0)) < 0) {
				zend_string_release(payload);
				spprintf(msg, 0, "unable to send data");
				return 0;
			}
		}

		bytes_sent = ret - sizeof(yar_header_t);
		bytes_left = ZSTR_LEN(payload) - bytes_sent;

wait_io:
		if (bytes_left) {
			retval = php_select(fd+1, NULL, &rfds, NULL, &tv);

			if (retval == -1) {
				zend_string_release(payload);
				spprintf(msg, 0, "select error '%s'", strerror(errno));
				return 0;
			} else if (retval == 0) {
				zend_string_release(payload);
				spprintf(msg, 0, "select timeout %ldms reached", YAR_G(timeout));
				return 0;
			}

			if (PHP_SAFE_FD_ISSET(fd, &rfds)) {
				if ((ret = php_stream_xport_sendto(data->stream, ZSTR_VAL(payload) + bytes_sent, bytes_left, 0, NULL, 0)) > 0) {
					bytes_left -= ret;
					bytes_sent += ret;
				}
			}
			goto wait_io;
		}
	}

	zend_string_release(payload);

	return ret < 0? 0 : 1;
} /* }}} */
Пример #3
0
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;
	}
} /* }}} */