Exemplo n.º 1
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;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
static void http_client_coro_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 *retval = NULL;
    http_client *http = swoole_get_object(zobject);
    if (!http->cli)
    {
        swoole_php_fatal_error(E_WARNING, "object is not instanceof swoole_http_client_coro.");
        return;
    }
    //timeout
    if (cli->timeout_id > 0)
    {
        php_swoole_clear_timer_coro(cli->timeout_id TSRMLS_CC);
        cli->timeout_id=0;
    }

    long parsed_n = php_http_parser_execute(&http->parser, &http_parser_settings, data, length);

    http_client_property *hcc = swoole_get_property(zobject, 0);
    zval *zdata;
    SW_MAKE_STD_ZVAL(zdata);

    if (parsed_n < 0)
    {
        //错误情况 标志位 done defer 保存
        sw_zend_call_method_with_0_params(&zobject, swoole_http_client_coro_class_entry_ptr, NULL, "close", &retval);
        if (retval)
        {
            sw_zval_ptr_dtor(&retval);
        }
        ZVAL_BOOL(zdata, 0); //return false
        if (hcc->defer && hcc->defer_status != HTTP_CLIENT_STATE_DEFER_WAIT)
        {
            //not recv yet  sava data
            hcc->defer_status = HTTP_CLIENT_STATE_DEFER_DONE;
            hcc->defer_result = 0;
            goto free_zdata;
            //wait for recv
        }
        goto begin_resume;
    }

    //not complete
    if (!http->completed)
    {
        return;
    }


//    if(!hcc->defer_chunk_status){ //not recv all wait for next
//        return;
//    }

    ZVAL_BOOL(zdata, 1); //return false
    if (hcc->defer && hcc->defer_status != HTTP_CLIENT_STATE_DEFER_WAIT)
    {
        //not recv yet  sava data
        hcc->defer_status = HTTP_CLIENT_STATE_DEFER_DONE;
        hcc->defer_result = 1;
        goto free_zdata;
    }

    begin_resume:
    {
        //if should resume
        /*if next cr*/
        php_context *sw_current_context = swoole_get_property(zobject, 1);
        hcc->defer_status = HTTP_CLIENT_STATE_DEFER_INIT;
    //    hcc->defer_chunk_status = 0;
        http->completed = 0;

        int ret = coro_resume(sw_current_context, zdata, &retval);
        if (ret > 0)
        {
            goto free_zdata;
        }
        if (retval != NULL)
        {
            sw_zval_ptr_dtor(&retval);
        }
    }

    free_zdata:
    sw_zval_ptr_dtor(&zdata);
}