예제 #1
0
static sw_inline void http2_onRequest(http_context *ctx, int server_fd TSRMLS_DC)
{
    zval *retval;
    zval **args[2];

    zval *zrequest_object = ctx->request.zobject;
    zval *zresponse_object = ctx->response.zobject;

    args[0] = &zrequest_object;
    args[1] = &zresponse_object;

    zval *zcallback = php_swoole_server_get_callback(SwooleG.serv, server_fd, SW_SERVER_CB_onRequest);
    if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "onRequest handler error");
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
    sw_zval_ptr_dtor(&zrequest_object);
    sw_zval_ptr_dtor(&zresponse_object);
}
예제 #2
0
static void php_swoole_event_onDefer(void *_cb)
{
    php_defer_callback *defer = _cb;

#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    zval *retval;
    if (sw_call_user_function_ex(EG(function_table), NULL, defer->callback, &retval, 0, NULL, 0, NULL TSRMLS_CC) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_event: defer handler error");
        return;
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval != NULL)
    {
        sw_zval_ptr_dtor(&retval);
    }
    sw_zval_ptr_dtor(&defer->callback);
    efree(defer);
}
예제 #3
0
static int php_swoole_event_onRead(swReactor *reactor, swEvent *event)
{
    zval *retval;
    zval args[1];
    php_reactor_fd *fd = event->socket->object;


    args[0] = *fd->socket;

    if (sw_call_user_function_ex(EG(function_table), NULL, fd->cb_read, &retval, 1, args, 0, NULL) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_event: onRead handler error.");
        SwooleG.main_reactor->del(SwooleG.main_reactor, event->fd);
        return SW_ERR;
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR);
    }
    if (retval != NULL)
    {
        zval_ptr_dtor(retval);
    }
    return SW_OK;
}
예제 #4
0
static int php_swoole_event_onWrite(swReactor *reactor, swEvent *event)
{
    zval *retval;
    zval **args[1];
    php_reactor_fd *fd = event->socket->object;

#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    if (!fd->cb_write)
    {
        return swReactor_onWrite(reactor, event);
    }

    args[0] = &fd->socket;

    if (sw_call_user_function_ex(EG(function_table), NULL, fd->cb_write, &retval, 1, args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_event: onWrite handler error");
        SwooleG.main_reactor->del(SwooleG.main_reactor, event->fd);
        return SW_ERR;
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval != NULL)
    {
        sw_zval_ptr_dtor(&retval);
    }
    return SW_OK;
}
예제 #5
0
static sw_inline void redis_execute_connect_callback(swRedisClient *redis, int success TSRMLS_DC)
{
    zval *result, *retval;
    SW_MAKE_STD_ZVAL(result);
    ZVAL_BOOL(result, success);

    zval **args[2];
    zval *zcallback = sw_zend_read_property(swoole_redis_class_entry_ptr, redis->object, ZEND_STRL("onConnect"), 0 TSRMLS_CC);
    args[0] = &redis->object;
    args[1] = &result;
    redis->connecting = 1;
    if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) != SUCCESS)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_async_redis connect_callback handler error.");
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval != NULL)
    {
        sw_zval_ptr_dtor(&retval);
    }
    sw_zval_ptr_dtor(&result);
    redis->connecting = 0;
}
예제 #6
0
static void php_swoole_aio_onDNSCompleted(swAio_event *event)
{
    int64_t ret;

    zval *retval = NULL, *zcallback = NULL;
    zval **args[2];
    dns_request *dns_req = NULL;

    zval _zcontent;

    dns_req = (dns_request *) event->req;
    zcallback = dns_req->callback;

    ret = event->ret;
    if (ret < 0)
    {
        SwooleG.error = event->error;
        swoole_php_error(E_WARNING, "Aio Error: %s[%d]", strerror(event->error), event->error);
    }

    args[0] = &dns_req->domain;
    zval *zcontent = &_zcontent;
    if (ret < 0)
    {
        SW_ZVAL_STRING(zcontent, "", 1);
    }
    else
    {
        SW_ZVAL_STRING(zcontent, event->buf, 1);
    }
    args[1] = &zcontent;

    if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete handler error");
        return;
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR);
    }

    sw_zval_ptr_dtor(&dns_req->callback);
    sw_zval_ptr_dtor(&dns_req->domain);
    efree(dns_req);
    efree(event->buf);

    if (zcontent)
    {
        sw_zval_ptr_dtor(&zcontent);
    }
    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
}
예제 #7
0
int swoole_websocket_onMessage(swEventData *req)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    int fd = req->info.fd;
    zval *zdata;
    SW_MAKE_STD_ZVAL(zdata);
    zdata = php_swoole_get_recv_data(zdata, req TSRMLS_CC);

    char *buf = Z_STRVAL_P(zdata);
    long finish = buf[0] ? 1 : 0;
    long opcode = buf[1] ? 1 : 0;

    zval *zframe;
    SW_MAKE_STD_ZVAL(zframe);
    object_init_ex(zframe, swoole_websocket_frame_class_entry_ptr);

    zend_update_property_long(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("fd"), fd TSRMLS_CC);
    zend_update_property_long(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("finish"), finish TSRMLS_CC);
    zend_update_property_long(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("opcode"), opcode TSRMLS_CC);
    zend_update_property_stringl(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("data"), buf + 2, (Z_STRLEN_P(zdata) - 2) TSRMLS_CC);

    swServer *serv = SwooleG.serv;
    zval *zserv = (zval *) serv->ptr2;

    zval **args[2];
    args[0] = &zserv;
    args[1] = &zframe;

    zval *retval = NULL;

    if (sw_call_user_function_ex(EG(function_table), NULL, websocket_callbacks[WEBSOCKET_CALLBACK_onMessage], &retval, 2,
            args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "onMessage handler error");
    }

    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }

    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }

    sw_zval_ptr_dtor(&zdata);
    sw_zval_ptr_dtor(&zframe);

    return SW_OK;
}
예제 #8
0
static sw_inline void client_execute_callback(swClient *cli, enum client_callback_type type)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif


    zval *callback = NULL;
    zval *retval = NULL;
    zval **args[1];
    zval *zobject = cli->object;

    client_callback *cb = swoole_get_property(zobject, 0);
    char *callback_name;

    switch(type)
    {
    case SW_CLIENT_CALLBACK_onConnect:
        callback = cb->onConnect;
        callback_name = "onConnect";
        break;
    case SW_CLIENT_CALLBACK_onError:
        callback = cb->onError;
        callback_name = "onError";
        break;
    case SW_CLIENT_CALLBACK_onClose:
        callback = cb->onClose;
        callback_name = "onClose";
        break;
    default:
        return;
    }

    if (callback == NULL || ZVAL_IS_NULL(callback))
    {
        swoole_php_fatal_error(E_WARNING, "object have not %s callback.", callback_name);
        return;
    }

    args[0] = &zobject;
    if (sw_call_user_function_ex(EG(function_table), NULL, callback, &retval, 1, args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "%s handler error.", callback_name);
        return;
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
}
예제 #9
0
int swoole_websocket_onMessage(swEventData *req)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    int fd = req->info.fd;

    zval *zdata;
    SW_MAKE_STD_ZVAL(zdata);

    char frame_header[2];
    php_swoole_get_recv_data(zdata, req, frame_header, 2);

    long finish = frame_header[0] ? 1 : 0;
    long opcode = frame_header[1];

    zval *zframe;
    SW_MAKE_STD_ZVAL(zframe);
    object_init_ex(zframe, swoole_websocket_frame_class_entry_ptr);

    zend_update_property_long(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("fd"), fd TSRMLS_CC);
    zend_update_property_bool(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("finish"), finish TSRMLS_CC);
    zend_update_property_long(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("opcode"), opcode TSRMLS_CC);
    zend_update_property(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("data"), zdata TSRMLS_CC);

    swServer *serv = SwooleG.serv;
    zval *zserv = (zval *) serv->ptr2;

    zval **args[2];
    args[0] = &zserv;
    args[1] = &zframe;

    zval *retval = NULL;
    zval *zcallback = php_swoole_server_get_callback(serv, req->info.from_fd, SW_SERVER_CB_onMessage);
    if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "onMessage handler error");
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
    sw_zval_ptr_dtor(&zdata);
    sw_zval_ptr_dtor(&zframe);
    return SW_OK;
}
예제 #10
0
static void php_swoole_dns_callback(char *domain, swDNSResolver_result *result, void *data)
{
    SWOOLE_GET_TSRMLS;
    dns_request *req = data;
    zval *retval = NULL;
    zval *zaddress;
    zval **args[2];
    char *address;

    SW_MAKE_STD_ZVAL(zaddress);
    if (result->num > 0)
    {
        if (SwooleG.dns_lookup_random)
        {
            address = result->hosts[rand() % result->num].address;
        }
        else
        {
            address = result->hosts[0].address;
        }
        SW_ZVAL_STRING(zaddress, address, 1);
    }
    else
    {
        SW_ZVAL_STRING(zaddress, "", 1);
    }

    args[0] = &req->domain;
    args[1] = &zaddress;

    zval *zcallback = req->callback;
    if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_asyns_dns_lookup handler error.");
        return;
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }

    sw_zval_ptr_dtor(&req->callback);
    sw_zval_ptr_dtor(&req->domain);
    efree(req);
    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
    sw_zval_ptr_dtor(&zaddress);
}
예제 #11
0
void swoole_websocket_onOpen(swoole_http_client *client)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    int fd = client->fd;

    swConnection *conn = swWorker_get_connection(SwooleG.serv, fd);
    if (!conn)
    {
        swWarn("connection[%d] is closed.", fd);
        return;
    }
    conn->websocket_status = WEBSOCKET_STATUS_HANDSHAKE;

    swTrace("\n\n\n\nconn ws status:%d, fd=%d\n\n\n", conn->websocket_status, fd);

    if (websocket_callbacks[WEBSOCKET_CALLBACK_onOpen])
    {
        swTrace("\n\n\n\nhandshake success\n\n\n");

        zval **args[2];
        swServer *serv = SwooleG.serv;
        zval *zserv = (zval *) serv->ptr2;
        zval *zrequest_object = client->request.zrequest_object;
        zval *retval = NULL;

#ifdef __CYGWIN__
        //TODO: memory error on cygwin.
        sw_zval_add_ref(&zrequest_object);
#endif

        args[0] = &zserv;
        args[1] = &zrequest_object;

        if (sw_call_user_function_ex(EG(function_table), NULL, websocket_callbacks[WEBSOCKET_CALLBACK_onOpen], &retval, 2, args, 0,  NULL TSRMLS_CC) == FAILURE)
        {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "onOpen handler error");
        }
        if (EG(exception))
        {
            zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
        }
        if (retval)
        {
            sw_zval_ptr_dtor(&retval);
        }
    }
}
예제 #12
0
static void php_swoole_onTimeout(swTimer *timer, swTimer_node *event)
{
    swTimer_callback *cb = event->data;
    zval *retval = NULL;
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    zval **args[1];
    int argc = 0;

    if (cb->data)
    {
        args[0] = &cb->data;
        argc = 1;
    }

    timer->_current_id = event->id;
    if (sw_call_user_function_ex(EG(function_table), NULL, cb->callback, &retval, argc, args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_timer: onTimeout handler error");
        return;
    }
    timer->_current_id = -1;

    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }

    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
    cb = event->data;
    if (cb)
    {
        if (cb->data)
        {
            sw_zval_ptr_dtor(&cb->data);
        }
        sw_zval_ptr_dtor(&cb->callback);
        efree(cb);
    }
}
예제 #13
0
ZEND_API ZEND_COLD void zend_throw_exception_internal(zval *exception) /* {{{ */
{
#ifdef HAVE_DTRACE
	if (DTRACE_EXCEPTION_THROWN_ENABLED()) {
		if (exception != NULL) {
			DTRACE_EXCEPTION_THROWN(ZSTR_VAL(Z_OBJ_P(exception)->ce->name));
		} else {
			DTRACE_EXCEPTION_THROWN(NULL);
		}
	}
#endif /* HAVE_DTRACE */

	if (exception != NULL) {
		zend_object *previous = EG(exception);
		zend_exception_set_previous(Z_OBJ_P(exception), EG(exception));
		EG(exception) = Z_OBJ_P(exception);
		if (previous) {
			return;
		}
	}
	if (!EG(current_execute_data)) {
		if (exception && Z_OBJCE_P(exception) == zend_ce_parse_error) {
			return;
		}
		if(EG(exception)) {
			zend_exception_error(EG(exception), E_ERROR);
		}
		zend_error_noreturn(E_CORE_ERROR, "Exception thrown without a stack frame");
	}

	if (zend_throw_exception_hook) {
		zend_throw_exception_hook(exception);
	}

	if (!EG(current_execute_data)->func ||
	    !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
	    EG(current_execute_data)->opline->opcode == ZEND_HANDLE_EXCEPTION) {
		/* no need to rethrow the exception */
		return;
	}
	EG(opline_before_exception) = EG(current_execute_data)->opline;
	EG(current_execute_data)->opline = EG(exception_op);
}
예제 #14
0
static void php_swoole_event_onEndCallback(void *_cb)
{
    php_defer_callback *defer = _cb;

    zval *retval;
    if (sw_call_user_function_ex(EG(function_table), NULL, defer->callback, &retval, 0, NULL, 0, NULL) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_event: defer handler error");
        return;
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR);
    }
    if (retval != NULL)
    {
        zval_ptr_dtor(retval);
    }
}
예제 #15
0
static void client_onReceive(swClient *cli, char *data, uint32_t length)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    zval *zobject = cli->object;
    zval *zcallback = NULL;
    zval **args[2];
    zval *retval;

    zval *zdata;
    SW_MAKE_STD_ZVAL(zdata);
    SW_ZVAL_STRINGL(zdata, data, length, 1);

    args[0] = &zobject;
    args[1] = &zdata;

    client_callback *cb = swoole_get_property(zobject, 0);
    zcallback = cb->onReceive;
    if (zcallback == NULL || ZVAL_IS_NULL(zcallback))
    {
        swoole_php_fatal_error(E_WARNING, "swoole_client object have not receive callback.");
        goto free_zdata;
    }

    if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "onReactorCallback handler error");
        goto free_zdata;
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval != NULL)
    {
        sw_zval_ptr_dtor(&retval);
    }
free_zdata:
    sw_zval_ptr_dtor(&zdata);
}
예제 #16
0
void swoole_websocket_onOpen(http_context *ctx)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    int fd = ctx->fd;

    swConnection *conn = swWorker_get_connection(SwooleG.serv, fd);
    if (!conn)
    {
        swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED, "session[%d] is closed.", fd);
        return;
    }
    conn->websocket_status = WEBSOCKET_STATUS_ACTIVE;

    zval *zcallback = php_swoole_server_get_callback(SwooleG.serv, conn->from_fd, SW_SERVER_CB_onOpen);
    if (zcallback)
    {
        zval **args[2];
        swServer *serv = SwooleG.serv;
        zval *zserv = (zval *) serv->ptr2;
        zval *zrequest_object = ctx->request.zobject;
        zval *retval = NULL;

        args[0] = &zserv;
        args[1] = &zrequest_object;

        if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0,  NULL TSRMLS_CC) == FAILURE)
        {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "onOpen handler error");
        }
        if (EG(exception))
        {
            zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
        }
        if (retval)
        {
            sw_zval_ptr_dtor(&retval);
        }
    }
}
예제 #17
0
static void handshake_success(int fd)
{
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
    SwooleG.lock.lock(&SwooleG.lock);
    swConnection *conn = swServer_connection_get(SwooleG.serv, fd);
    if (conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) {
        conn->websocket_status = WEBSOCKET_STATUS_HANDSHAKE;
    }
    SwooleG.lock.unlock(&SwooleG.lock);
    swTrace("\n\n\n\nconn ws status:%d\n\n\n", conn->websocket_status);

    if (php_sw_http_server_callbacks[3] != NULL)
    {
        swTrace("\n\n\n\nhandshake success\n\n\n");
        zval *zresponse;
        MAKE_STD_ZVAL(zresponse);
        object_init_ex(zresponse, swoole_http_wsresponse_class_entry_ptr);
        //socket fd
        zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("fd"), fd TSRMLS_CC);

        zval **args[1];
        args[0] = &zresponse;
        zval *retval;

        if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[3], &retval, 1, args, 0, NULL TSRMLS_CC) == FAILURE)
        {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "onMessage handler error");
        }
        swTrace("===== message callback end======");
        if (EG(exception)) {
            zend_exception_error(EG(exception), E_ERROR
            TSRMLS_CC);
        }
        if (retval) {
            zval_ptr_dtor(&retval);
        }
    }
}
예제 #18
0
static PHP_METHOD(swoole_coroutine_util, create)
{
    zval *callback;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callback) == FAILURE)
    {
        return;
    }

    sw_zval_add_ref(&callback);
    callback = sw_zval_dup(callback);

    char *func_name = NULL;
    zend_fcall_info_cache *func_cache = emalloc(sizeof(zend_fcall_info_cache));
    if (!sw_zend_is_callable_ex(callback, NULL, 0, &func_name, NULL, func_cache, NULL TSRMLS_CC))
    {
        swoole_php_fatal_error(E_ERROR, "Function '%s' is not callable", func_name);
        sw_zval_free(callback);
        efree(func_name);
        return;
    }
    efree(func_name);

    php_swoole_check_reactor();

    if (swReactorCheckPoint == NULL)
    {
        coro_init(TSRMLS_C);
    }

    zval *retval = NULL;
    zval *args[1];

    jmp_buf *prev_checkpoint = swReactorCheckPoint;
    swReactorCheckPoint = emalloc(sizeof(jmp_buf));

    php_context *cxt = emalloc(sizeof(php_context));
    coro_save(cxt);
    int ret = coro_create(func_cache, args, 0, &retval, NULL, NULL);
    efree(func_cache);
    efree(swReactorCheckPoint);

    if (ret < 0)
    {
        sw_zval_free(callback);
        RETURN_FALSE;
    }
    //save callback
    COROG.current_coro->function = callback;

    swReactorCheckPoint = prev_checkpoint;
    coro_resume_parent(cxt, retval, retval);
    efree(cxt);
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval != NULL)
    {
        sw_zval_ptr_dtor(&retval);
    }
    RETURN_TRUE;
}
예제 #19
0
static int process_stream_onRead(swReactor *reactor, swEvent *event)
{
    SWOOLE_GET_TSRMLS;

    process_stream *ps = event->socket->object;
    char *buf = ps->buffer->str + ps->buffer->length;
    size_t len = ps->buffer->size - ps->buffer->length;

    int ret = read(event->fd, buf, len);
    if (ret > 0)
    {
        ps->buffer->length += ret;
        if (ps->buffer->length == ps->buffer->size)
        {
            swString_extend(ps->buffer, ps->buffer->size * 2);
        }
        return SW_OK;
    }
    else if (ret < 0)
    {
        swSysError("read() failed.");
        return SW_OK;
    }

    zval *retval = NULL;
    zval **args[2];

    zval *zdata;
    SW_MAKE_STD_ZVAL(zdata);
    SW_ZVAL_STRINGL(zdata, ps->buffer->str, ps->buffer->length, 1);

    SwooleG.main_reactor->del(SwooleG.main_reactor, ps->fd);

    swString_free(ps->buffer);
    args[0] = &zdata;

    int status;
    zval *zstatus;
    SW_MAKE_STD_ZVAL(zstatus);

    pid_t pid = swWaitpid(ps->pid, &status, WNOHANG);
    if (pid > 0)
    {
        array_init(zstatus);
        add_assoc_long(zstatus, "code", WEXITSTATUS(status));
        add_assoc_long(zstatus, "signal", WTERMSIG(status));
    }
    else
    {
        ZVAL_FALSE(zstatus);
    }

    args[1] = &zstatus;

    zval *zcallback = ps->callback;

    if (zcallback)
    {
        if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE)
        {
            swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete handler error");
        }
        sw_zval_free(zcallback);
    }
    else
    {
#ifdef SW_COROUTINE
        php_context *context = ps->context;
        sw_zval_add_ref(&zdata);
        add_assoc_zval(zstatus, "output", zdata);
        int ret = coro_resume(context, zstatus, &retval);
        if (ret == CORO_END && retval)
        {
            sw_zval_ptr_dtor(&retval);
        }
        efree(context);
#else
        return SW_OK;
#endif
    }

    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval != NULL)
    {
        sw_zval_ptr_dtor(&retval);
    }
    sw_zval_ptr_dtor(&zdata);
    sw_zval_ptr_dtor(&zstatus);
    close(ps->fd);
    efree(ps);

    return SW_OK;
}
예제 #20
0
static void php_swoole_aio_onFileCompleted(swAio_event *event)
{
    int isEOF = SW_FALSE;
    int64_t ret;

    zval *retval = NULL, *zcallback = NULL, *zwriten = NULL;
    zval *zcontent = NULL;
    zval **args[2];

    zval _zcontent;
    zval _zwriten;
    bzero(&_zcontent, sizeof(zval));
    bzero(&_zwriten, sizeof(zval));

    file_request *file_req = event->object;
    zcallback = file_req->callback;

    ret = event->ret;
    if (ret < 0)
    {
        SwooleG.error = event->error;
        swoole_php_error(E_WARNING, "Aio Error: %s[%d]", strerror(event->error), event->error);
    }
    else
    {
        if (ret == 0)
        {
            bzero(event->buf, event->nbytes);
            isEOF = SW_TRUE;
        }
        else if (file_req->once == 1 && ret < file_req->length)
        {
            swoole_php_fatal_error(E_WARNING, "ret_length[%d] < req->length[%d].", (int ) ret, file_req->length);
        }
        else if (event->type == SW_AIO_READ)
        {
            file_req->offset += event->ret;
        }
    }

    if (event->type == SW_AIO_READ)
    {
        args[0] = &file_req->filename;
        args[1] = &zcontent;
        zcontent = &_zcontent;
        if (ret < 0)
        {
            SW_ZVAL_STRING(zcontent, "", 1);
        }
        else
        {
            SW_ZVAL_STRINGL(zcontent, event->buf, ret, 1);
        }
    }
    else if (event->type == SW_AIO_WRITE)
    {
        zwriten = &_zwriten;
        args[0] = &file_req->filename;
        args[1] = &zwriten;
        ZVAL_LONG(zwriten, ret);
    }
    else
    {
        swoole_php_fatal_error(E_WARNING, "swoole_async: onFileCompleted unknown event type[%d].", event->type);
        return;
    }

    if (zcallback)
    {
        if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE)
        {
            swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete handler error");
            return;
        }
        if (EG(exception))
        {
            zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
        }
    }

    //file io
    if (file_req->once == 1)
    {
        close_file:
        close(event->fd);
        php_swoole_file_request_free(file_req);
    }
    else if(file_req->type == SW_AIO_WRITE)
    {
        if (retval != NULL && !ZVAL_IS_NULL(retval) && !Z_BVAL_P(retval))
        {
            swHashMap_del(php_swoole_open_files, Z_STRVAL_P(file_req->filename), Z_STRLEN_P(file_req->filename));
            goto close_file;
        }
        else
        {
            php_swoole_file_request_free(file_req);
        }
    }
    else
    {
        if ((retval != NULL && !ZVAL_IS_NULL(retval) && !Z_BVAL_P(retval)) || isEOF)
        {
            goto close_file;
        }
        //Less than expected, at the end of the file
        else if (event->ret < event->nbytes)
        {
            event->ret = 0;
            php_swoole_aio_onFileCompleted(event);
        }
        //continue to read
        else
        {
            swAio_event ev;
            ev.fd = event->fd;
            ev.buf = event->buf;
            ev.type = SW_AIO_READ;
            ev.nbytes = event->nbytes;
            ev.offset = file_req->offset;
            ev.flags = 0;
            ev.object = file_req;
            ev.handler = swAio_handler_read;
            ev.callback = php_swoole_aio_onFileCompleted;

            int ret = swAio_dispatch(&ev);
            if (ret < 0)
            {
                swoole_php_fatal_error(E_WARNING, "swoole_async: continue to read failed. Error: %s[%d]", strerror(event->error), event->error);
                goto close_file;
            }
        }
    }

    if (zcontent)
    {
        sw_zval_ptr_dtor(&zcontent);
    }
    if (zwriten)
    {
        sw_zval_ptr_dtor(&zwriten);
    }
    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
}
예제 #21
0
static int http_onReceive(swFactory *factory, swEventData *req)
{
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);

    int fd = req->info.fd;
    http_client *client = swHashMap_find_int(php_sw_http_clients, fd);

    if (!client)
    {
        client = http_client_new(fd TSRMLS_CC);
    }
    php_http_parser *parser = &client->parser;

    zval *zrequest;
    MAKE_STD_ZVAL(zrequest);
    object_init_ex(zrequest, swoole_http_request_class_entry_ptr);

    zval *header;
    MAKE_STD_ZVAL(header);

    //request header
    array_init(header);
    zend_update_property(swoole_http_request_class_entry_ptr, zrequest, ZEND_STRL("header"), header TSRMLS_CC);

    zval *zresponse;
    MAKE_STD_ZVAL(zresponse);
    object_init_ex(zresponse, swoole_http_response_class_entry_ptr);

    //socket fd
    zend_update_property_long(swoole_http_response_class_entry_ptr, zresponse, ZEND_STRL("fd"), fd TSRMLS_CC);

    client->zresponse = zresponse;
    client->zrequest = zrequest;

    parser->data = client;
    php_http_parser_init(parser, PHP_HTTP_REQUEST);

    zval *zdata = php_swoole_get_data(req TSRMLS_CC);
    size_t n = php_http_parser_execute(parser, &http_parser_settings, Z_STRVAL_P(zdata), Z_STRLEN_P(zdata));
    zval_ptr_dtor(&zdata);

    if (n < 0)
    {
        swWarn("php_http_parser_execute failed.");
    }
    else
    {
        zval *retval;
        zval **args[2];

        args[0] = &zrequest;
        args[1] = &zresponse;

        if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[0], &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE)
        {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "onRequest handler error");
        }
        if (EG(exception))
        {
            zend_exception_error(EG(exception), E_WARNING TSRMLS_CC);
        }
        if (retval)
        {
            zval_ptr_dtor(&retval);
        }
    }
    return SW_OK;
}
예제 #22
0
static void php_swoole_onTimerInterval(swTimer *timer, swTimer_node *event)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    zval *retval = NULL;
    zval **args[2];
    int argc = 1;

    zval *ztimer_id;

    swTimer_callback *cb = event->data;

    //server->addtimer
    if (cb == NULL && SwooleG.serv)
    {
        SwooleG.serv->onTimer(SwooleG.serv, event->interval);
        return;
    }

    if (cb->type == SW_TIMER_TICK)
    {
        SW_MAKE_STD_ZVAL(ztimer_id);
        ZVAL_LONG(ztimer_id, event->id);

        if (cb->data)
        {
            argc = 2;
            sw_zval_add_ref(&cb->data);
            args[1] = &cb->data;
        }
    }
    else
    {
        SW_MAKE_STD_ZVAL(ztimer_id);
        ZVAL_LONG(ztimer_id, event->interval);
    }
    args[0] = &ztimer_id;

    timer->_current_id = event->id;
    if (sw_call_user_function_ex(EG(function_table), NULL, cb->callback, &retval, argc, args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_timer: onTimerCallback handler error");
        return;
    }
    timer->_current_id = -1;

    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }

    if (retval != NULL)
    {
        sw_zval_ptr_dtor(&retval);
    }

    if (SwooleG.timer._delete_id == event->id)
    {
        php_swoole_del_timer(SwooleG.timer._delete_id  TSRMLS_CC);
        SwooleG.timer._delete_id = -1;
    }
    sw_zval_ptr_dtor(&ztimer_id);
}
void swoole_websocket_onOpen(http_context *ctx)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    int fd = ctx->fd;

    swConnection *conn = swWorker_get_connection(SwooleG.serv, fd);
    if (!conn)
    {
        swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED, "session[%d] is closed.", fd);
        return;
    }
    conn->websocket_status = WEBSOCKET_STATUS_ACTIVE;

    zend_fcall_info_cache *cache = php_swoole_server_get_cache(SwooleG.serv, conn->from_fd, SW_SERVER_CB_onOpen);
    if (cache)
    {
        swServer *serv = SwooleG.serv;
        zval *zserv = (zval *) serv->ptr2;
        zval *zrequest_object = ctx->request.zobject;
        zval *retval = NULL;

#ifndef SW_COROUTINE
        zval **args[2];
        args[0] = &zserv;
        args[1] = &zrequest_object;
#else
        zval *args[2];
        args[0] = zserv;
        args[1] = zrequest_object;
#endif

#ifndef SW_COROUTINE
        zval *zcallback = php_swoole_server_get_callback(SwooleG.serv, conn->from_fd, SW_SERVER_CB_onOpen);
        if (sw_call_user_function_fast(zcallback, cache, &retval, 2, args TSRMLS_CC) == FAILURE)
        {
            swoole_php_error(E_WARNING, "onOpen handler error");
        }
#else
        int ret = coro_create(cache, args, 2, &retval, NULL, NULL);
        if (ret != 0)
        {
            if (ret == CORO_LIMIT)
            {
                SwooleG.serv->factory.end(&SwooleG.serv->factory, fd);
            }
            return;
        }
#endif
        if (EG(exception))
        {
            zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
        }
        if (retval)
        {
            sw_zval_ptr_dtor(&retval);
        }
    }
}
int swoole_websocket_onMessage(swEventData *req)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    int fd = req->info.fd;

    zval *zdata;
    SW_MAKE_STD_ZVAL(zdata);

    char frame_header[2];
    php_swoole_get_recv_data(zdata, req, frame_header, 2);

    long finish = frame_header[0] ? 1 : 0;
    long opcode = frame_header[1];

    zval *zframe;
    SW_MAKE_STD_ZVAL(zframe);
    object_init_ex(zframe, swoole_websocket_frame_class_entry_ptr);

    zend_update_property_long(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("fd"), fd TSRMLS_CC);
    zend_update_property_bool(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("finish"), finish TSRMLS_CC);
    zend_update_property_long(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("opcode"), opcode TSRMLS_CC);
    zend_update_property(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("data"), zdata TSRMLS_CC);

    swServer *serv = SwooleG.serv;
    zval *zserv = (zval *) serv->ptr2;

#ifndef SW_COROUTINE
    zval **args[2];
    args[0] = &zserv;
    args[1] = &zframe;
#else
    zval *args[2];
    args[0] = zserv;
    args[1] = zframe;
#endif

    zval *retval = NULL;

#ifndef SW_COROUTINE
    zend_fcall_info_cache *fci_cache = php_swoole_server_get_cache(serv, req->info.from_fd, SW_SERVER_CB_onMessage);
    zval *zcallback = php_swoole_server_get_callback(SwooleG.serv, req->info.from_fd, SW_SERVER_CB_onMessage);
    if (sw_call_user_function_fast(zcallback, fci_cache, &retval, 2, args TSRMLS_CC) == FAILURE)
    {
        swoole_php_error(E_WARNING, "onMessage handler error");
    }
#else
    zend_fcall_info_cache *cache = php_swoole_server_get_cache(serv, req->info.from_fd, SW_SERVER_CB_onMessage);
    int ret = coro_create(cache, args, 2, &retval, NULL, NULL);
    if (ret != 0)
    {
        sw_zval_ptr_dtor(&zdata);
        sw_zval_ptr_dtor(&zframe);
        if (ret == CORO_LIMIT)
        {
            SwooleG.serv->factory.end(&SwooleG.serv->factory, fd);
        }
        return SW_OK;
    }
#endif
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
    sw_zval_ptr_dtor(&zdata);
    sw_zval_ptr_dtor(&zframe);
    return SW_OK;
}
예제 #25
0
static int http_onReceive(swFactory *factory, swEventData *req)
{
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);

    int fd = req->info.fd;


//    swTrace("on receive:%s pid:%d\n", zdata, getpid());
    swConnection *conn = swServer_connection_get(SwooleG.serv, fd);

    if(conn->websocket_status == WEBSOCKET_STATUS_HANDSHAKE)  //websocket callback
    {
        zval *zdata = php_swoole_get_data(req TSRMLS_CC);
        swTrace("on message callback\n");
        char *buf = Z_STRVAL_P(zdata);
        long fin = buf[0] ? 1 : 0;
        long opcode = buf[1] ? 1 : 0;
        buf+=2;
        zval *zresponse;
        MAKE_STD_ZVAL(zresponse);
        object_init_ex(zresponse, swoole_http_wsresponse_class_entry_ptr);
        //socket fd
        zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("fd"), fd TSRMLS_CC);
        zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("fin"), fin TSRMLS_CC);
        zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("opcode"), opcode TSRMLS_CC);
        zend_update_property_stringl(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("data"), buf, (Z_STRLEN_P(zdata)-2) TSRMLS_CC);

        zval **args[1];
        args[0] = &zresponse;
        zval *retval;
        if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[1], &retval, 1, args, 0, NULL TSRMLS_CC) == FAILURE)
        {
            zval_ptr_dtor(&zdata);
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "onMessage handler error");
        }
        swTrace("===== message callback end======");
        if (EG(exception))
        {
            zval_ptr_dtor(&zdata);
            zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
        }
        if (retval)
        {
            zval_ptr_dtor(&retval);
        }
        zval_ptr_dtor(&zdata);
        return SW_OK;
    }

    http_client *client = swHashMap_find_int(php_sw_http_clients, fd);



    if (!client)
    {
        client = http_client_new(fd TSRMLS_CC);
    }


    php_http_parser *parser = &client->parser;

    /**
     * create request and response object
     */
    http_request_new(client TSRMLS_CC);

    parser->data = client;
    php_http_parser_init(parser, PHP_HTTP_REQUEST);



    zval *zdata = php_swoole_get_data(req TSRMLS_CC);
    //server info
    zval *_request;
    MAKE_STD_ZVAL(_request);
    array_init(_request);
    zend_update_property(swoole_http_request_class_entry_ptr, client->zrequest, ZEND_STRL("request"), _request TSRMLS_CC);
    size_t n = php_http_parser_execute(parser, &http_parser_settings, Z_STRVAL_P(zdata), Z_STRLEN_P(zdata));
    zval_ptr_dtor(&zdata);
    if (n < 0)
    {
        swWarn("php_http_parser_execute failed.");
        if(conn->websocket_status == WEBSOCKET_STATUS_CONNECTION)
        {
            SwooleG.serv->factory.end(&SwooleG.serv->factory, fd);
        }

    }
    else
    {
        if(conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) // need handshake
        {
            if(php_sw_http_server_callbacks[2] == NULL) {
                int ret = websocket_handshake(client);
                http_request_free(client TSRMLS_CC);
                if (ret == SW_ERR) {
                    swTrace("websocket handshake error\n");
                    SwooleG.serv->factory.end(&SwooleG.serv->factory, fd);
                } else {
                    handshake_success(fd);
                    swTrace("websocket handshake_success\n");
                    return SW_OK;
                }
                return ret;
            }
        }

        zval *retval;
        zval **args[2];
        zval *zrequest = client->zrequest;

    	//server info
    	zval *zserver;
    	MAKE_STD_ZVAL(zserver);
    	array_init(zserver);
    	zend_update_property(swoole_http_request_class_entry_ptr, zrequest, ZEND_STRL("server"), zserver TSRMLS_CC);

        switch (parser->method) {
            case PHP_HTTP_GET: add_assoc_string(zserver, "REQUEST_METHOD", "GET", 1);break;
            case PHP_HTTP_POST: add_assoc_string(zserver, "REQUEST_METHOD", "POST", 1);break;
            case PHP_HTTP_HEAD: add_assoc_string(zserver, "REQUEST_METHOD", "HEAD", 1);break;
            case PHP_HTTP_PUT: add_assoc_string(zserver, "REQUEST_METHOD", "PUT", 1);break;
            case PHP_HTTP_DELETE: add_assoc_string(zserver, "REQUEST_METHOD", "DELETE", 1);break;
            case PHP_HTTP_PATCH: add_assoc_string(zserver, "REQUEST_METHOD", "PATCH", 1);break;
                /* pathological */
            case PHP_HTTP_CONNECT: add_assoc_string(zserver, "REQUEST_METHOD", "CONNECT", 1);break;
            case PHP_HTTP_OPTIONS: add_assoc_string(zserver, "REQUEST_METHOD", "OPTIONS", 1);break;
            case PHP_HTTP_TRACE: add_assoc_string(zserver, "REQUEST_METHOD", "TRACE", 1);break;
                /* webdav */
            case PHP_HTTP_COPY: add_assoc_string(zserver, "REQUEST_METHOD", "COPY", 1);break;
            case PHP_HTTP_LOCK: add_assoc_string(zserver, "REQUEST_METHOD", "LOCK", 1);break;
            case PHP_HTTP_MKCOL: add_assoc_string(zserver, "REQUEST_METHOD", "MKCOL", 1);break;
            case PHP_HTTP_MOVE: add_assoc_string(zserver, "REQUEST_METHOD", "MOVE", 1);break;
            case PHP_HTTP_PROPFIND: add_assoc_string(zserver, "REQUEST_METHOD", "PROPFIND", 1);break;
            case PHP_HTTP_PROPPATCH: add_assoc_string(zserver, "REQUEST_METHOD", "PROPPATCH", 1);break;
            case PHP_HTTP_UNLOCK: add_assoc_string(zserver, "REQUEST_METHOD", "UNLOCK", 1);break;
                /* subversion */
            case PHP_HTTP_REPORT: add_assoc_string(zserver, "REQUEST_METHOD", "REPORT", 1);break;
            case PHP_HTTP_MKACTIVITY: add_assoc_string(zserver, "REQUEST_METHOD", "MKACTIVITY", 1);break;
            case PHP_HTTP_CHECKOUT: add_assoc_string(zserver, "REQUEST_METHOD", "CHECKOUT", 1);break;
            case PHP_HTTP_MERGE: add_assoc_string(zserver, "REQUEST_METHOD", "MERGE", 1);break;
                /* upnp */
            case PHP_HTTP_MSEARCH: add_assoc_string(zserver, "REQUEST_METHOD", "MSEARCH", 1);break;
            case PHP_HTTP_NOTIFY: add_assoc_string(zserver, "REQUEST_METHOD", "NOTIFY", 1);break;
            case PHP_HTTP_SUBSCRIBE: add_assoc_string(zserver, "REQUEST_METHOD", "SUBSCRIBE", 1);break;
            case PHP_HTTP_UNSUBSCRIBE: add_assoc_string(zserver, "REQUEST_METHOD", "UNSUBSCRIBE", 1);break;
            case PHP_HTTP_NOT_IMPLEMENTED: add_assoc_string(zserver, "REQUEST_METHOD", "GET", 1);break;
        }

//    	if (parser->method == PHP_HTTP_POST)
//    	{
//    		add_assoc_string(zserver, "REQUEST_METHOD", "POST", 1);
//    	}
//    	else
//    	{
//    		add_assoc_string(zserver, "REQUEST_METHOD", "GET", 1);
//    	}

    	add_assoc_stringl(zserver, "REQUEST_URI", client->request.path, client->request.path_len, 1);
    	add_assoc_stringl(zserver, "PATH_INFO", client->request.path, client->request.path_len, 1);
    	add_assoc_long_ex(zserver,  ZEND_STRS("REQUEST_TIME"), SwooleGS->now);

    	swConnection *conn = swServer_connection_get(SwooleG.serv, fd);
    	add_assoc_long(zserver, "SERVER_PORT", SwooleG.serv->connection_list[conn->from_fd].addr.sin_port);
    	add_assoc_long(zserver, "REMOTE_PORT", ntohs(conn->addr.sin_port));
    	add_assoc_string(zserver, "REMOTE_ADDR", inet_ntoa(conn->addr.sin_addr), 1);

    	if (client->request.version == 101)
    	{
    		add_assoc_string(zserver, "SERVER_PROTOCOL", "HTTP/1.1", 1);
    	}
    	else
    	{
            add_assoc_string(zserver, "SERVER_PROTOCOL", "HTTP/1.0", 1);
        }
        add_assoc_string(zserver, "SERVER_SOFTWARE", SW_HTTP_SERVER_SOFTWARE, 1);
        add_assoc_string(zserver, "GATEWAY_INTERFACE", SW_HTTP_SERVER_SOFTWARE, 1);
//        ZEND_SET_SYMBOL(&EG(symbol_table), "_SERVER", zserver);


    	zval *zresponse;
    	MAKE_STD_ZVAL(zresponse);
    	object_init_ex(zresponse, swoole_http_response_class_entry_ptr);

    	//socket fd
    	zend_update_property_long(swoole_http_response_class_entry_ptr, zresponse, ZEND_STRL("fd"), client->fd TSRMLS_CC);
    	client->zresponse = zresponse;

        args[0] = &zrequest;
        args[1] = &zresponse;

        int called = 0;
        if(conn->websocket_status == WEBSOCKET_STATUS_CONNECTION)
        {
            called = 2;
        }
        if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[called], &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE)
        {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "onRequest handler error");
        }
        if (EG(exception))
        {
            zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
        }
        if (retval)
        {
            zval_ptr_dtor(&retval);
        }
        swTrace("======call end======\n");
        if(called == 2) {
            handshake_success(fd);
        }
    }
    return SW_OK;
}
예제 #26
0
static swVal* swoole_call_php_func(const char *name, int length)
{
#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#endif

    int i;
    zval **args[SW_PHP_FUNCTION_MAX_ARG];
    zval *zval_array[SW_PHP_FUNCTION_MAX_ARG];
#if PHP_MAJOR_VERSION >= 7
    zval _zval_array[SW_PHP_FUNCTION_MAX_ARG];
#endif
    zval *arg;

    uint32_t offset = 0;
    swVal *val;
    void *params = SwooleG.call_php_func_args->str;

    for (i = 0; i < SwooleG.call_php_func_argc; i++)
    {
#if PHP_MAJOR_VERSION >= 7
        zval_array[i] = &_zval_array[i];
#else
        SW_ALLOC_INIT_ZVAL(zval_array[i]);
#endif
        arg = zval_array[i];
        val = params + offset;
        if (swVal_to_zval(val, arg) < 0)
        {
            return NULL;
        }
        args[i] = &zval_array[i];
        offset += sizeof(swVal) + val->length;
    }

    zval *func_name;
    zval *retval = NULL;
    SW_MAKE_STD_ZVAL(func_name);
    SW_ZVAL_STRING(func_name, name, 1);

    if (sw_call_user_function_ex(EG(function_table), NULL, func_name, &retval, SwooleG.call_php_func_argc, args, 0, NULL TSRMLS_CC) == FAILURE)
    {
        swoole_php_fatal_error(E_WARNING, "swoole_server: onPipeMessage handler error");
        return NULL;
    }
    if (EG(exception))
    {
        zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
    }
    //clear input buffer
    swArgs_clear();
    for (i = 0; i < SwooleG.call_php_func_argc; i++)
    {
        sw_zval_ptr_dtor(&zval_array[i]);
    }
    //return value
    if (!retval)
    {
        return NULL;
    }
    swVal *val_c = NULL;
    switch(Z_TYPE_P(retval))
    {
#if PHP_MAJOR_VERSION < 7
    case IS_BOOL:
        val_c = sw_malloc(sizeof(swVal) + 1);
        swVal_bool(val_c, Z_BVAL_P(retval));
        break;
#else
    case IS_TRUE:
        val_c = sw_malloc(sizeof(swVal) + 1);
        swVal_bool(val_c, 1);
        break;
    case IS_FALSE:
        val_c = sw_malloc(sizeof(swVal) + 1);
        swVal_bool(val_c, 0);
        break;
#endif
    case IS_STRING:
        val_c = sw_malloc(sizeof(swVal) + Z_STRLEN_P(retval) + 1);
        swVal_string(val_c, Z_STRVAL_P(retval) , Z_STRLEN_P(retval));
        break;
    case IS_LONG:
        val_c = sw_malloc(sizeof(swVal) + sizeof(long));
        swVal_long(val_c, Z_LVAL_P(retval));
        break;
    case IS_DOUBLE:
        val_c = sw_malloc(sizeof(swVal) + sizeof(double));
        swVal_double(val_c, Z_DVAL_P(retval));
        break;
    case IS_NULL:
        return NULL;
    default:
        swWarn("unknown type.");
        break;
    }
    sw_zval_ptr_dtor(&retval);
    return val_c;
}
예제 #27
0
static void php_swoole_aio_onComplete(swAio_event *event)
{
    int isEOF = SW_FALSE;
    int64_t ret;

    zval *retval = NULL, *zcallback = NULL, *zwriten = NULL;
    zval *zcontent = NULL;
    zval **args[2];
    file_request *file_req = NULL;
    dns_request *dns_req = NULL;

#if PHP_MAJOR_VERSION < 7
    TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL);
#else
    zval _zcontent;
    zval _zwriten;
    bzero(&_zcontent, sizeof(zval));
    bzero(&_zwriten, sizeof(zval));
#endif

    if (event->type == SW_AIO_GETHOSTBYNAME)
    {
        dns_req = (dns_request *) event->req;
        if (dns_req->callback == NULL)
        {
            swoole_php_error(E_WARNING, "swoole_async: onAsyncComplete callback not found[0]");
            return;
        }
        zcallback = dns_req->callback;
    }
    else
    {
        file_req = swHashMap_find_int(php_swoole_aio_request, event->task_id);
        if (!file_req)
        {
            swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete callback not found[1]");
            return;
        }
        if (file_req->callback == NULL && file_req->type == SW_AIO_READ)
        {
            swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete callback not found[2]");
            return;
        }
        zcallback = file_req->callback;
    }

    ret = event->ret;
    if (ret < 0)
    {
        SwooleG.error = event->error;
        swoole_php_error(E_WARNING, "Aio Error: %s[%d]", strerror(event->error), event->error);
    }
    else if (file_req != NULL)
    {
        if (ret == 0)
        {
            bzero(event->buf, event->nbytes);
            isEOF = SW_TRUE;
        }
        else if (file_req->once == 1 && ret < file_req->length)
        {
            swoole_php_fatal_error(E_WARNING, "ret_length[%d] < req->length[%d].", (int ) ret, file_req->length);
        }
        else if (event->type == SW_AIO_READ)
        {
            file_req->offset += event->ret;
        }
    }

    if (event->type == SW_AIO_READ)
    {
        args[0] = &file_req->filename;
        args[1] = &zcontent;
#if PHP_MAJOR_VERSION < 7
        SW_MAKE_STD_ZVAL(zcontent);
#else
        zcontent = &_zcontent;
#endif
        if (ret < 0)
        {
            SW_ZVAL_STRING(zcontent, "", 1);
        }
        else
        {
            SW_ZVAL_STRINGL(zcontent, event->buf, ret, 1);
        }
    }
    else if (event->type == SW_AIO_WRITE)
    {
#if PHP_MAJOR_VERSION < 7
        SW_MAKE_STD_ZVAL(zwriten);
#else
        zwriten = &_zwriten;
#endif
        args[0] = &file_req->filename;
        args[1] = &zwriten;
        ZVAL_LONG(zwriten, ret);
    }
    else if(event->type == SW_AIO_GETHOSTBYNAME)
    {
        args[0] = &dns_req->domain;
#if PHP_MAJOR_VERSION < 7
        SW_MAKE_STD_ZVAL(zcontent);
#else
        zcontent = &_zcontent;
#endif
        if (ret < 0)
        {
            SW_ZVAL_STRING(zcontent, "", 1);
        }
        else
        {
            SW_ZVAL_STRING(zcontent, event->buf, 1);
        }
        args[1] = &zcontent;
    }
    else
    {
        swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete unknown event type[%d].", event->type);
        return;
    }

    if (zcallback)
    {
        if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE)
        {
            swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete handler error");
            return;
        }
        if (EG(exception))
        {
            zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
        }
    }

    //file io
    if (file_req)
    {
        if (file_req->once == 1)
        {
            close_file:
            close(event->fd);
            swHashMap_del_int(php_swoole_aio_request, event->task_id);
        }
        else if(file_req->type == SW_AIO_WRITE)
        {
            if (retval != NULL && !ZVAL_IS_NULL(retval) && !Z_BVAL_P(retval))
            {
                swHashMap_del(php_swoole_open_files, Z_STRVAL_P(file_req->filename), Z_STRLEN_P(file_req->filename));
                goto close_file;
            }
            else
            {
                swHashMap_del_int(php_swoole_aio_request, event->task_id);
            }
        }
        else
        {
            if ((retval != NULL && !ZVAL_IS_NULL(retval) && !Z_BVAL_P(retval)) || isEOF)
            {
                goto close_file;
            }
            //Less than expected, at the end of the file
            else if (event->ret < event->nbytes)
            {
                event->ret = 0;
                php_swoole_aio_onComplete(event);
            }
            //continue to read
            else
            {
                int ret = SwooleAIO.read(event->fd, event->buf, event->nbytes, file_req->offset);
                if (ret < 0)
                {
                    swoole_php_fatal_error(E_WARNING, "swoole_async: continue to read failed. Error: %s[%d]", strerror(event->error), event->error);
                    goto close_file;
                }
                else
                {
                    swHashMap_move_int(php_swoole_aio_request, event->task_id, ret);
                }
            }
        }
    }
    else if (dns_req)
    {
        sw_zval_ptr_dtor(&dns_req->callback);
        sw_zval_ptr_dtor(&dns_req->domain);
        efree(dns_req);
        efree(event->buf);
    }
    if (zcontent)
    {
        sw_zval_ptr_dtor(&zcontent);
    }
    if (zwriten)
    {
        sw_zval_ptr_dtor(&zwriten);
    }
    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
}