예제 #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;
    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;
}
예제 #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;


//    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;
}