static PHP_METHOD(swoole_http2_client_coro, __construct)
{
    char *host;
    zend_size_t host_len;
    long port = 80;
    zend_bool ssl = SW_FALSE;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &host, &host_len, &port, &ssl) == FAILURE)
    {
        return;
    }

    if (host_len <= 0)
    {
        zend_throw_exception(swoole_exception_class_entry_ptr, "host is empty.", SW_ERROR_INVALID_PARAMS TSRMLS_CC);
        RETURN_FALSE;
    }

    http2_client_property *hcc;
    hcc = (http2_client_property*) emalloc(sizeof(http2_client_property));
    bzero(hcc, sizeof(http2_client_property));
    swoole_set_property(getThis(), HTTP2_CLIENT_CORO_PROPERTY, hcc);

    php_context *context = emalloc(sizeof(php_context));
    swoole_set_property(getThis(), HTTP2_CLIENT_CORO_CONTEXT, context);
    context->onTimeout = NULL;
#if PHP_MAJOR_VERSION < 7
    context->coro_params = getThis();
#else
    context->coro_params = *getThis();
#endif

    hcc->streams = swHashMap_new(8, http2_client_stream_free);
    hcc->stream_id = 1;

    long type = SW_FLAG_ASYNC | SW_SOCK_TCP;
    if (ssl)
    {
#ifdef SW_USE_OPENSSL
        type |= SW_SOCK_SSL;
        hcc->ssl = 1;
#else
        swoole_php_fatal_error(E_ERROR, "require openssl library.");
#endif
    }

    zend_update_property_long(swoole_http2_client_coro_class_entry_ptr, getThis(), ZEND_STRL("type"), type TSRMLS_CC);

    hcc->host = estrndup(host, host_len);
    hcc->host_len = host_len;
    hcc->port = port;
}
static PHP_METHOD(swoole_server_port, __destruct)
{
    swoole_server_port_property *property = swoole_get_property(getThis(), 0);
    efree(property);
    swoole_set_property(getThis(), 0, NULL);
    swoole_set_object(getThis(), NULL);
}
static PHP_METHOD(swoole_server_port, __destruct)
{
    swoole_port_callbacks *callbacks = swoole_get_property(getThis(), 0);
    efree(callbacks);
    swoole_set_property(getThis(), 0, NULL);
    swoole_set_object(getThis(), NULL);
}
static PHP_METHOD(swoole_http2_client, __construct)
{
    char *host;
    zend_size_t host_len;
    long port = 80;
    zend_bool ssl = SW_FALSE;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &host, &host_len, &port, &ssl) == FAILURE)
    {
        return;
    }

    if (host_len <= 0)
    {
        zend_throw_exception(swoole_exception_class_entry_ptr, "host is empty.", SW_ERROR_INVALID_PARAMS TSRMLS_CC);
        RETURN_FALSE;
    }

    http2_client_property *hcc;
    hcc = (http2_client_property*) emalloc(sizeof(http2_client_property));
    bzero(hcc, sizeof(http2_client_property));
    swoole_set_property(getThis(), HTTP2_CLIENT_PROPERTY_INDEX, hcc);

    hcc->requests = swLinkedList_new(0, http2_client_request_free);
    hcc->stream_requests = swLinkedList_new(0, http2_client_request_free);
    hcc->streams = swHashMap_new(8, http2_client_stream_free);
    hcc->stream_id = 1;

    zval *ztype;
    SW_MAKE_STD_ZVAL(ztype);
    long type = SW_FLAG_ASYNC | SW_SOCK_TCP;
    if (ssl)
    {
        type |= SW_SOCK_SSL;
        hcc->ssl = 1;
    }
    ZVAL_LONG(ztype, type);

    zval *zobject = getThis();
    zval *retval = NULL;
    sw_zend_call_method_with_1_params(&zobject, swoole_client_class_entry_ptr, NULL, "__construct", &retval, ztype);
    if (retval)
    {
        sw_zval_ptr_dtor(&retval);
    }
    sw_zval_ptr_dtor(&ztype);

    hcc->host = estrndup(host, host_len);
    hcc->host_len = host_len;
    hcc->port = port;
}
static sw_inline void client_free_php_context(zval *object)
{
    //free memory
    php_context *context = swoole_get_property(object, 1);
    if (!context)
    {
        return;
    }

    if (likely(context->state == SW_CORO_CONTEXT_RUNNING))
    {
        efree(context);
    }
    else
    {
        context->state = SW_CORO_CONTEXT_TERM;
    }
    swoole_set_property(object, 1, NULL);
}