Exemplo n.º 1
0
/*
 * suspend current coroutine
 */
static PHP_METHOD(swoole_coroutine_util, yield)
{
    int cid = sw_get_current_cid();
    if (cid < 0)
    {
        swoole_php_fatal_error(E_ERROR, "can not yield outside coroutine");
        RETURN_FALSE;
    }

    swLinkedList *coros_list = swHashMap_find_int(defer_coros, cid);
    if (coros_list == NULL)
    {
        coros_list = swLinkedList_new(2, NULL);
        if (coros_list == NULL)
        {
            RETURN_FALSE;
        }
        if (swHashMap_add_int(defer_coros, cid, coros_list) == SW_ERR)
        {
            swLinkedList_free(coros_list);
            RETURN_FALSE;
        }
    }

    php_context *context = emalloc(sizeof(php_context));
    coro_save(context);
    if (swLinkedList_append(coros_list, (void *) context) == SW_ERR)
    {
        efree(context);
        RETURN_FALSE;
    }
    coro_yield();
}
Exemplo n.º 2
0
static void co_socket_read(int fd, zend_long length, INTERNAL_FUNCTION_PARAMETERS)
{
    php_swoole_check_reactor();
    if (!swReactor_handle_isset(SwooleG.main_reactor, PHP_SWOOLE_FD_SOCKET))
    {
        SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_CO_UTIL | SW_EVENT_READ, co_socket_onReadable);
        SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_CO_UTIL | SW_EVENT_WRITE, co_socket_onWritable);
    }

    if (SwooleG.main_reactor->add(SwooleG.main_reactor, fd, PHP_SWOOLE_FD_CO_UTIL | SW_EVENT_READ) < 0)
    {
        SwooleG.error = errno;
        RETURN_FALSE;
    }

    swConnection *_socket = swReactor_get(SwooleG.main_reactor, fd);
    util_socket *sock = emalloc(sizeof(util_socket));
    bzero(sock, sizeof(util_socket));
    _socket->object = sock;

    sock->fd = fd;
    sock->buf = zend_string_alloc(length + 1, 0);
    sock->nbytes = length <= 0 ? SW_BUFFER_SIZE_STD : length;

    sock->context.state = SW_CORO_CONTEXT_RUNNING;

    coro_save(&sock->context);
    coro_yield();
}
Exemplo n.º 3
0
static PHP_METHOD(swoole_coroutine_util, suspend)
{
    char *id;
    int id_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",&id, &id_len) == FAILURE)
    {
        return;
    }

    swLinkedList *coros_list = swHashMap_find(defer_coros, id, id_len);
    if (coros_list == NULL)
    {
        coros_list = swLinkedList_new(2, NULL);
        if (coros_list == NULL)
        {
            RETURN_FALSE;
        }
        if (swHashMap_add(defer_coros, id, id_len, coros_list) == SW_ERR)
        {
            swLinkedList_free(coros_list);
            RETURN_FALSE;
        }
    }

    php_context *context = emalloc(sizeof(php_context));
    coro_save(context);
    if (swLinkedList_append(coros_list, (void *)context) == SW_ERR) {
        efree(context);
        RETURN_FALSE;
    }
    coro_yield();
}
Exemplo n.º 4
0
static PHP_METHOD(swoole_coroutine_util, cli_wait) {
    if (SwooleGS->start == 1) {
        RETURN_FALSE;
    }
    php_context *cxt = emalloc(sizeof(php_context));
    coro_save(cxt);
    php_swoole_event_wait();
    coro_resume_parent(cxt, NULL, NULL);
    efree(cxt);
    RETURN_LONG(COROG.coro_num);
}
Exemplo n.º 5
0
static PHP_METHOD(swoole_coroutine_util, readFile)
{
    coro_check(TSRMLS_C);

    char *filename = NULL;
    size_t l_filename = 0;

#ifdef FAST_ZPP
    ZEND_PARSE_PARAMETERS_START(1, 2)
        Z_PARAM_STRING(filename, l_filename)
    ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
#else
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &l_filename) == FAILURE)
    {
        return;
    }
#endif

    swAio_event ev;
    bzero(&ev, sizeof(swAio_event));

    php_context *context = emalloc(sizeof(php_context));

    ev.type = SW_AIO_READ_FILE;
    ev.object = context;
    ev.handler = swAio_handler_read_file;
    ev.callback = aio_onReadFileCompleted;
    ev.req = estrndup(filename, l_filename);

    if (!SwooleAIO.init)
    {
        php_swoole_check_reactor();
        swAio_init();
    }

    swTrace("readFile(%s)", filename);

    int ret = swAio_dispatch(&ev);
    if (ret < 0)
    {
        efree(context);
        RETURN_FALSE;
    }

    context->state = SW_CORO_CONTEXT_RUNNING;

    coro_save(context);
    coro_yield();
}
Exemplo n.º 6
0
static PHP_METHOD(swoole_coroutine_util, sleep)
{
    coro_check(TSRMLS_C);

    double seconds;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", & seconds) == FAILURE)
    {
        return;
    }

    int ms = (int) (seconds * 1000);

    if (SwooleG.serv && swIsMaster())
    {
        swoole_php_fatal_error(E_WARNING, "cannot use timer in master process.");
        return;
    }
    if (ms > SW_TIMER_MAX_VALUE)
    {
        swoole_php_fatal_error(E_WARNING, "The given parameters is too big.");
        return;
    }
    if (ms <= 0)
    {
        swoole_php_fatal_error(E_WARNING, "Timer must be greater than 0");
        return;
    }

    php_context *context = emalloc(sizeof(php_context));
    context->onTimeout = NULL;
    context->state = SW_CORO_CONTEXT_RUNNING;

    php_swoole_check_reactor();
    php_swoole_check_timer(ms);
    if (SwooleG.timer.add(&SwooleG.timer, ms, 0, context, php_coroutine_sleep_timeout) == NULL)
    {
        RETURN_FALSE;
    }

    coro_save(context);
    coro_yield();
}
Exemplo n.º 7
0
static void co_socket_write(int fd, char* str, size_t l_str, INTERNAL_FUNCTION_PARAMETERS)
{
    int ret = write(fd, str, l_str);
    if (ret < 0)
    {
        if (errno == EAGAIN)
        {
            goto _yield;
        }
        SwooleG.error = errno;
        RETURN_FALSE;
    }
    else
    {
        RETURN_LONG(ret);
    }

    _yield: if (SwooleG.main_reactor->add(SwooleG.main_reactor, fd, PHP_SWOOLE_FD_SOCKET | SW_EVENT_WRITE) < 0)
    {
        SwooleG.error = errno;
        RETURN_FALSE;
    }

    swConnection *_socket = swReactor_get(SwooleG.main_reactor, fd);
    util_socket *sock = emalloc(sizeof(util_socket));
    bzero(sock, sizeof(util_socket));
    _socket->object = sock;

    php_context *context = &sock->context;
    context->state = SW_CORO_CONTEXT_RUNNING;
    context->private_data = str;

    sock->nbytes = l_str;

    coro_save(context);
    coro_yield();
}
Exemplo n.º 8
0
static PHP_METHOD(swoole_coroutine_util, fgets)
{
    coro_check(TSRMLS_C);

    zval *handle;
    php_stream *stream;

#ifdef FAST_ZPP
    ZEND_PARSE_PARAMETERS_START(1, 2)
        Z_PARAM_RESOURCE(handle)
    ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
#else
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &handle) == FAILURE)
    {
        return;
    }
#endif

    int async;
    int fd = swoole_convert_to_fd_ex(handle, &async);
    if (fd < 0)
    {
        RETURN_FALSE;
    }

    if (async == 1)
    {
        swoole_php_fatal_error(E_WARNING, "only support file resources.");
        RETURN_FALSE;
    }

    swAio_event ev;
    bzero(&ev, sizeof(swAio_event));

    php_stream_from_res(stream, Z_RES_P(handle));

    if (stream->readbuf == NULL)
    {
        stream->readbuflen = stream->chunk_size;
        stream->readbuf = emalloc(stream->chunk_size);
    }

    ev.nbytes = stream->readbuflen;
    ev.buf = stream->readbuf;
    if (!ev.buf)
    {
        RETURN_FALSE;
    }

    php_context *context = emalloc(sizeof(php_context));

    ev.flags = 0;
    ev.type = SW_AIO_STREAM_GET_LINE;
    ev.object = context;
    ev.callback = aio_onStreamGetLineCompleted;
    ev.handler = swAio_handler_stream_get_line;
    ev.fd = fd;
    ev.offset = stream->readpos;
    ev.req = (void *) (long) stream->writepos;

    if (!SwooleAIO.init)
    {
        php_swoole_check_reactor();
        swAio_init();
    }

    swTrace("fd=%d, offset=%jd, length=%ld", fd, (intmax_t) ev.offset, ev.nbytes);

    int ret = swAio_dispatch(&ev);
    if (ret < 0)
    {
        efree(context);
        RETURN_FALSE;
    }

    context->coro_params = *handle;
    context->state = SW_CORO_CONTEXT_RUNNING;

    coro_save(context);
    coro_yield();
}
Exemplo n.º 9
0
static PHP_METHOD(swoole_coroutine_util, fread)
{
    coro_check(TSRMLS_C);

    zval *handle;
    zend_long length = 0;

#ifdef FAST_ZPP
    ZEND_PARSE_PARAMETERS_START(1, 2)
        Z_PARAM_RESOURCE(handle)
        Z_PARAM_OPTIONAL
        Z_PARAM_LONG(length)
    ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
#else
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &handle, &length) == FAILURE)
    {
        return;
    }
#endif

    int async;
    int fd = swoole_convert_to_fd_ex(handle, &async TSRMLS_CC);
    if (fd < 0)
    {
        RETURN_FALSE;
    }

    if (async)
    {
        co_socket_read(fd, length, INTERNAL_FUNCTION_PARAM_PASSTHRU);
        return;
    }

    struct stat file_stat;
    if (fstat(fd, &file_stat) < 0)
    {
        SwooleG.error = errno;
        RETURN_FALSE;
    }

    off_t _seek = lseek(fd, 0, SEEK_CUR);
    if (_seek < 0)
    {
        SwooleG.error = errno;
        RETURN_FALSE;
    }
    if (length <= 0 || file_stat.st_size - _seek < length)
    {
        length = file_stat.st_size - _seek;
    }

    swAio_event ev;
    bzero(&ev, sizeof(swAio_event));

    ev.nbytes = length + 1;
    ev.buf = emalloc(ev.nbytes);
    if (!ev.buf)
    {
        RETURN_FALSE;
    }

    php_context *context = emalloc(sizeof(php_context));

    ((char *) ev.buf)[length] = 0;
    ev.flags = 0;
    ev.type = SW_AIO_READ;
    ev.object = context;
    ev.handler = swAio_handler_read;
    ev.callback = aio_onReadCompleted;
    ev.fd = fd;
    ev.offset = _seek;

    if (!SwooleAIO.init)
    {
        php_swoole_check_reactor();
        swAio_init();
    }

    swTrace("fd=%d, offset=%jd, length=%ld", fd, (intmax_t) ev.offset, ev.nbytes);

    int ret = swAio_dispatch(&ev);
    if (ret < 0)
    {
        efree(context);
        RETURN_FALSE;
    }

    context->state = SW_CORO_CONTEXT_RUNNING;

    coro_save(context);
    coro_yield();
}
Exemplo n.º 10
0
static PHP_METHOD(swoole_coroutine_util, getaddrinfo)
{
    coro_check(TSRMLS_C);

    char *hostname;
    zend_size_t l_hostname;
    long family = AF_INET;
    long socktype = SOCK_STREAM;
    long protocol = IPPROTO_TCP;
    char *service = NULL;
    zend_size_t l_service = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "s|llls", &hostname, &l_hostname, &family, socktype, &protocol,
            &hostname, &l_hostname) == FAILURE)
    {
        RETURN_FALSE;
    }

    if (l_hostname <= 0)
    {
        swoole_php_fatal_error(E_WARNING, "hostname is empty.");
        RETURN_FALSE;
    }

    if (family != AF_INET && family != AF_INET6)
    {
        swoole_php_fatal_error(E_WARNING, "unknown protocol family, must be AF_INET or AF_INET6.");
        RETURN_FALSE;
    }

    swAio_event ev;
    bzero(&ev, sizeof(swAio_event));

    swRequest_getaddrinfo *req = emalloc(sizeof(swRequest_getaddrinfo));
    bzero(req, sizeof(swRequest_getaddrinfo));

    php_context *sw_current_context = emalloc(sizeof(php_context));

    ev.type = SW_AIO_GETADDRINFO;
    ev.object = sw_current_context;
    ev.handler = swAio_handler_getaddrinfo;
    ev.callback = coro_dns_onGetaddrinfoCompleted;
    ev.req = req;

    req->hostname = estrndup(hostname, l_hostname);
    req->family = family;
    req->socktype = socktype;
    req->protocol = protocol;

    if (service)
    {
        req->service = estrndup(service, l_service);
    }

    if (family == AF_INET)
    {
        req->result = ecalloc(SW_DNS_HOST_BUFFER_SIZE, sizeof(struct sockaddr_in));
    }
    else
    {
        req->result = ecalloc(SW_DNS_HOST_BUFFER_SIZE, sizeof(struct sockaddr_in6));
    }

    php_swoole_check_aio();

    if (swAio_dispatch(&ev) < 0)
    {
        efree(ev.buf);
        RETURN_FALSE;
    }

    coro_save(sw_current_context);
    coro_yield();
}
Exemplo n.º 11
0
static PHP_METHOD(swoole_coroutine_util, gethostbyname)
{
    coro_check(TSRMLS_C);

    char *domain_name;
    zend_size_t l_domain_name;
    long family = AF_INET;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &domain_name, &l_domain_name, &family) == FAILURE)
    {
        RETURN_FALSE;
    }

    if (l_domain_name <= 0)
    {
        swoole_php_fatal_error(E_WARNING, "domain name is empty.");
        RETURN_FALSE;
    }

    if (family != AF_INET && family != AF_INET6)
    {
        swoole_php_fatal_error(E_WARNING, "unknown protocol family, must be AF_INET or AF_INET6.");
        RETURN_FALSE;
    }

    swAio_event ev;
    bzero(&ev, sizeof(swAio_event));

    if (l_domain_name < SW_IP_MAX_LENGTH)
    {
        ev.nbytes = SW_IP_MAX_LENGTH;
    }
    else
    {
        ev.nbytes = l_domain_name + 1;
    }

    ev.buf = emalloc(ev.nbytes);
    if (!ev.buf)
    {
        swWarn("malloc failed.");
        RETURN_FALSE;
    }

    php_context *sw_current_context = emalloc(sizeof(php_context));

    memcpy(ev.buf, domain_name, l_domain_name);
    ((char *) ev.buf)[l_domain_name] = 0;
    ev.flags = family;
    ev.type = SW_AIO_GETHOSTBYNAME;
    ev.object = sw_current_context;
    ev.handler = swAio_handler_gethostbyname;
    ev.callback = coro_dns_onResolveCompleted;

    php_swoole_check_aio();

    if (swAio_dispatch(&ev) < 0)
    {
        efree(ev.buf);
        RETURN_FALSE;
    }

    coro_save(sw_current_context);
    coro_yield();
}
Exemplo n.º 12
0
static PHP_METHOD(swoole_coroutine_util, writeFile)
{
    coro_check(TSRMLS_C);

    char *filename = NULL;
    size_t l_filename = 0;
    char *data = NULL;
    size_t l_data = 0;
    zend_long flags = 0;

#ifdef FAST_ZPP
    ZEND_PARSE_PARAMETERS_START(2, 3)
        Z_PARAM_STRING(filename, l_filename)
        Z_PARAM_STRING(data, l_data)
        Z_PARAM_OPTIONAL
        Z_PARAM_LONG(flags)
    ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
#else
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &filename, &l_filename, &data, &l_data, &flags) == FAILURE)
    {
        return;
    }
#endif

    swAio_event ev;
    bzero(&ev, sizeof(swAio_event));

    ev.nbytes = l_data;
    ev.buf = data;

    php_context *context = emalloc(sizeof(php_context));

    ev.type = SW_AIO_WRITE_FILE;
    ev.object = context;
    ev.handler = swAio_handler_write_file;
    ev.callback = aio_onWriteFileCompleted;
    ev.req = estrndup(filename, l_filename);
    ev.flags = O_CREAT | O_WRONLY;

    if (flags & PHP_FILE_APPEND)
    {
        ev.flags |= O_APPEND;
    }
    else
    {
        ev.flags |= O_TRUNC;
    }

    if (!SwooleAIO.init)
    {
        php_swoole_check_reactor();
        swAio_init();
    }

    swTrace("writeFile(%s, %ld)", filename, ev.nbytes);

    int ret = swAio_dispatch(&ev);
    if (ret < 0)
    {
        efree(context);
        RETURN_FALSE;
    }

    context->state = SW_CORO_CONTEXT_RUNNING;

    coro_save(context);
    coro_yield();
}
Exemplo n.º 13
0
static PHP_METHOD(swoole_coroutine_util, fwrite)
{
    coro_check(TSRMLS_C);

    zval *handle;
    char *str;
    zend_size_t l_str;
    zend_long length = 0;

#ifdef FAST_ZPP
    ZEND_PARSE_PARAMETERS_START(2, 3)
        Z_PARAM_RESOURCE(handle)
        Z_PARAM_STRING(str, l_str)
        Z_PARAM_OPTIONAL
        Z_PARAM_LONG(length)
    ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
#else
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &handle, &str, &l_str, &length) == FAILURE)
    {
        return;
    }
#endif

    int async;
    int fd = swoole_convert_to_fd_ex(handle, &async TSRMLS_CC);
    if (fd < 0)
    {
        RETURN_FALSE;
    }

    if (async)
    {
        co_socket_write(fd, str, (length < 0 && length < l_str) ? length : l_str, INTERNAL_FUNCTION_PARAM_PASSTHRU);
        return;
    }

    off_t _seek = lseek(fd, 0, SEEK_CUR);
    if (_seek < 0)
    {
        SwooleG.error = errno;
        RETURN_FALSE;
    }
    if (length <= 0 || length > l_str)
    {
        length = l_str;
    }

    swAio_event ev;
    bzero(&ev, sizeof(swAio_event));

    ev.nbytes = length;
    ev.buf = estrndup(str, length);

    if (!ev.buf)
    {
        RETURN_FALSE;
    }

    php_context *context = emalloc(sizeof(php_context));

    ev.flags = 0;
    ev.type = SW_AIO_WRITE;
    ev.object = context;
    ev.handler = swAio_handler_write;
    ev.callback = aio_onWriteCompleted;
    ev.fd = fd;
    ev.offset = _seek;

    php_swoole_check_aio();

    swTrace("fd=%d, offset=%jd, length=%ld", fd, (intmax_t) ev.offset, ev.nbytes);

    int ret = swAio_dispatch(&ev);
    if (ret < 0)
    {
        efree(context);
        RETURN_FALSE;
    }

    context->state = SW_CORO_CONTEXT_RUNNING;

    coro_save(context);
    coro_yield();
}
Exemplo n.º 14
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;
}