📄 sockets.c
字号:
long arg1; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &arg1) == FAILURE) return; RETURN_STRING(php_strerror(arg1 TSRMLS_CC), 1);}/* }}} *//* {{{ proto bool socket_bind(resource socket, string addr [, int port]) Binds an open socket to a listening port, port is only specified in AF_INET family. */PHP_FUNCTION(socket_bind){ zval *arg1; php_sockaddr_storage sa_storage; struct sockaddr *sock_type = (struct sockaddr*) &sa_storage; php_socket *php_sock; char *addr; int addr_len; long port = 0; long retval = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) return; ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); switch(php_sock->type) { case AF_UNIX: { struct sockaddr_un *sa = (struct sockaddr_un *) sock_type; memset(sa, 0, sizeof(sa_storage)); sa->sun_family = AF_UNIX; snprintf(sa->sun_path, 108, "%s", addr); retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa, SUN_LEN(sa)); break; } case AF_INET: { struct sockaddr_in *sa = (struct sockaddr_in *) sock_type; memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */ sa->sin_family = AF_INET; sa->sin_port = htons((unsigned short) port); if (! php_set_inet_addr(sa, addr, php_sock TSRMLS_CC)) { RETURN_FALSE; } retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in)); break; } default: php_error(E_WARNING, "%s() unsupported socket type '%d', must be AF_UNIX or AF_INET", get_active_function_name(TSRMLS_C), php_sock->type); RETURN_FALSE; } if (retval != 0) { PHP_SOCKET_ERROR(php_sock, "unable to bind address", errno); RETURN_FALSE; } RETURN_TRUE;}/* }}} *//* {{{ proto resource socket_iovec_alloc(int num_vectors [, int ...]) Builds a 'struct iovec' for use with sendmsg, recvmsg, writev, and readv *//* First parameter is number of vectors, each additional parameter is the length of the vector to create. */PHP_FUNCTION(socket_iovec_alloc){ zval ***args = (zval ***)NULL; php_iovec_t *vector; struct iovec *vector_array; long num_vectors; int i, j, argc = ZEND_NUM_ARGS(); if(argc>65536) { WRONG_PARAM_COUNT; } args = safe_emalloc(sizeof(zval**), argc, 0); if (argc < 1 || zend_get_parameters_array_ex(argc, args) == FAILURE) { efree(args); WRONG_PARAM_COUNT; } convert_to_long_ex(args[0]); num_vectors = Z_LVAL_PP(args[0]); if(num_vectors < 0 || (argc-1) < num_vectors) { efree(args); WRONG_PARAM_COUNT; } vector_array = safe_emalloc(sizeof(struct iovec), (num_vectors + 1), 0); for (i = 0, j = 1; i < num_vectors; i++, j++) { convert_to_long_ex(args[j]); if(Z_LVAL_PP(args[j])<=0 || Z_LVAL_PP(args[j])>1048576) { php_error(E_WARNING, "%s() vector %d is invalid", get_active_function_name(TSRMLS_C), j); efree(args); efree(vector_array); RETURN_FALSE; } vector_array[i].iov_base = (char*)emalloc(Z_LVAL_PP(args[j])); vector_array[i].iov_len = Z_LVAL_PP(args[j]); } efree(args); vector = emalloc(sizeof(php_iovec_t)); vector->iov_array = vector_array; vector->count = num_vectors; ZEND_REGISTER_RESOURCE(return_value, vector, le_iov);}/* }}} *//* {{{ proto string socket_iovec_fetch(resource iovec, int iovec_position) Returns the data held in the iovec specified by iovec_id[iovec_position] */PHP_FUNCTION(socket_iovec_fetch){ zval *iovec_id; php_iovec_t *vector; unsigned long iovec_position; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &iovec_id, &iovec_position) == FAILURE) return; ZEND_FETCH_RESOURCE(vector, php_iovec_t *, &iovec_id, -1, le_iov_name, le_iov); if (iovec_position >= vector->count) { php_error(E_WARNING, "%s() can't access a vector position past the amount of vectors set in the array", get_active_function_name(TSRMLS_C)); RETURN_EMPTY_STRING(); } RETURN_STRINGL(vector->iov_array[iovec_position].iov_base, vector->iov_array[iovec_position].iov_len, 1);}/* }}} *//* {{{ proto bool socket_iovec_set(resource iovec, int iovec_position, string new_val) Sets the data held in iovec_id[iovec_position] to new_val */PHP_FUNCTION(socket_iovec_set){ zval *iovec_id; php_iovec_t *vector; int new_val_len; unsigned long iovec_position; char *new_val; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls", &iovec_id, &iovec_position, &new_val, &new_val_len) == FAILURE) return; ZEND_FETCH_RESOURCE(vector, php_iovec_t *, &iovec_id, -1, le_iov_name, le_iov); if (iovec_position >= vector->count) { php_error(E_WARNING, "%s() can't access a vector position outside of the vector array bounds", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } if (vector->iov_array[iovec_position].iov_base) { efree(vector->iov_array[iovec_position].iov_base); } vector->iov_array[iovec_position].iov_base = estrdup(new_val); vector->iov_array[iovec_position].iov_len = strlen(new_val); RETURN_TRUE;}/* }}} *//* {{{ proto bool socket_iovec_add(resource iovec, int iov_len) Adds a new vector to the scatter/gather array */PHP_FUNCTION(socket_iovec_add){ zval *iovec_id; php_iovec_t *vector; struct iovec *vector_array; long iov_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &iovec_id, &iov_len) == FAILURE) return; ZEND_FETCH_RESOURCE(vector, php_iovec_t *, &iovec_id, -1, le_iov_name, le_iov); vector_array = (struct iovec*)safe_emalloc(sizeof(struct iovec), (vector->count + 2), 0); memcpy(vector_array, vector->iov_array, sizeof(struct iovec) * vector->count); if (iov_len < 1) { RETURN_FALSE; } vector_array[vector->count].iov_base = (char*)emalloc(iov_len); vector_array[vector->count].iov_len = iov_len; efree(vector->iov_array); vector->iov_array = vector_array; vector->count++; RETURN_TRUE;}/* }}} *//* {{{ proto bool socket_iovec_delete(resource iovec, int iov_pos) Deletes a vector from an array of vectors */PHP_FUNCTION(socket_iovec_delete){ zval *iovec_id; php_iovec_t *vector; struct iovec *vector_array; unsigned int i; unsigned long iov_pos; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &iovec_id, &iov_pos) == FAILURE) return; ZEND_FETCH_RESOURCE(vector, php_iovec_t *, &iovec_id, -1, le_iov_name, le_iov); if (iov_pos > vector->count) { php_error(E_WARNING, "%s() can't delete an IO vector that is out of array bounds", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } vector_array = safe_emalloc(vector->count, sizeof(struct iovec), 0); for (i = 0; i < vector->count; i++) { if (i < iov_pos) { memcpy(&(vector->iov_array[i]), &(vector_array[i]), sizeof(struct iovec)); } else if (i > iov_pos) { memcpy(&(vector->iov_array[i]), &(vector_array[i - 1]), sizeof(struct iovec)); } } efree(vector->iov_array); vector->iov_array = vector_array; RETURN_TRUE;}/* }}} *//* {{{ proto bool socket_iovec_free(resource iovec) Frees the iovec specified by iovec_id */PHP_FUNCTION(socket_iovec_free){ zval *iovec_id; php_iovec_t *vector; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &iovec_id) == FAILURE) return; ZEND_FETCH_RESOURCE(vector, php_iovec_t *, &iovec_id, -1, le_iov_name, le_iov); zend_list_delete(Z_RESVAL_P(iovec_id)); RETURN_TRUE;}/* }}} *//* {{{ proto bool socket_readv(resource socket, resource iovec_id) Reads from an fd, using the scatter-gather array defined by iovec_id */PHP_FUNCTION(socket_readv){ zval *arg1, *arg2; php_iovec_t *vector; php_socket *php_sock; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &arg1, &arg2) == FAILURE) return; ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); ZEND_FETCH_RESOURCE(vector, php_iovec_t *, &arg2, -1, le_iov_name, le_iov); if (readv(php_sock->bsd_socket, vector->iov_array, vector->count) != 0) { PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno); RETURN_FALSE; } RETURN_TRUE;}/* }}} *//* {{{ proto bool socket_writev(resource socket, resource iovec_id) Writes to a file descriptor, fd, using the scatter-gather array defined by iovec_id */PHP_FUNCTION(socket_writev){ zval *arg1, *arg2; php_iovec_t *vector; php_socket *php_sock; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &arg1, &arg2) == FAILURE) return; ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); ZEND_FETCH_RESOURCE(vector, php_iovec_t *, &arg2, -1, le_iov_name, le_iov); if (writev(php_sock->bsd_socket, vector->iov_array, vector->count) != 0) { PHP_SOCKET_ERROR(php_sock, "Unable to write to socket", errno); RETURN_FALSE; } RETURN_TRUE;}/* }}} *//* {{{ proto int socket_recv(resource socket, string &buf, int len, int flags) Receives data from a connected socket */PHP_FUNCTION(socket_recv){ zval *php_sock_res, *buf; char *recv_buf; php_socket *php_sock; int retval; long len, flags; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzll", &php_sock_res, &buf, &len, &flags) == FAILURE) return; if(len<0) RETURN_FALSE; ZEND_FETCH_RESOURCE(php_sock, php_socket *, &php_sock_res, -1, le_socket_name, le_socket); /* overflow check */ if ((len + 1) < 2) { RETURN_FALSE; } recv_buf = emalloc(len + 1); memset(recv_buf, 0, len + 1); if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags)) < 1) { efree(recv_buf); zval_dtor(buf); Z_TYPE_P(buf) = IS_NULL; } else { recv_buf[retval] = '\0'; /* Rebuild buffer zval */ zval_dtor(buf); Z_STRVAL_P(buf) = recv_buf; Z_STRLEN_P(buf) = retval; Z_TYPE_P(buf) = IS_STRING; } if (retval == -1) { PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno); RETURN_FALSE; } RETURN_LONG(retval);}/* }}} *//* {{{ proto int socket_send(resource socket, string buf, int len, int flags) Sends data to a connected socket */PHP_FUNCTION(socket_send){ zval *arg1; php_socket *php_sock; int buf_len, retval; long len, flags; char *buf; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsll", &arg1, &buf, &buf_len, &len, &flags) == FAILURE) return; ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); retval = send(php_sock->bsd_socket, buf, (buf_len < len ? buf_len : len), flags); if (retval == -1) { PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno); RETURN_FALSE; } RETURN_LONG(retval);}/* }}} *//* {{{ proto int socket_recvfrom(resource socket, string &buf, int len, int flags, string &name [, int &port]) Receives data from a socket, connected or not */PHP_FUNCTION(socket_recvfrom){ zval *arg1, *arg2, *arg5, *arg6 = NULL; php_socket *php_sock; struct sockaddr_un s_un; struct sockaddr_in sin; socklen_t slen; int retval; long arg3, arg4; char *recv_buf, *address; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzllz|z", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) return; ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); if(arg3<0) RETURN_FALSE; /* overflow check */ if ((arg3 + 2) < 3) { RETURN_FALSE; } recv_buf = emalloc(arg3 + 2); memset(recv_buf, 0, arg3 + 2); switch (php_sock->type) { case AF_UNIX: slen = sizeof(s_un); s_un.sun_family = AF_UNIX; retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&s_un, (socklen_t *)&slen); if (retval < 0) { efree(recv_buf); PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno); RETURN_FALSE; } zval_dtor(arg2); zval_dtor(arg5); ZVAL_STRINGL(arg2, recv_buf, retval, 0); ZVAL_STRING(arg5, s_un.sun_path, 1); break; case AF_INET: slen = sizeof(sin); memset(&sin, 0, slen); sin.sin_family = AF_INET; if (arg6 == NULL) { WRONG_PARAM_COUNT; } retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&sin, (socklen_t *)&slen); if (retval < 0) { efree(recv_buf); PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno); RETURN_FALSE; } zval_dtor(arg2); zval_dtor(arg5); zval_dtor(arg6); address = inet_ntoa(sin.sin_addr); ZVAL_STRINGL(arg2, recv_buf, retval, 0); ZVAL_STRING(arg5, address ? address : "0.0.0.0", 1); ZVAL_LONG(arg6, ntohs(sin.sin_port)); break; default: php_error(E_WARNING, "%s() Unsupported socket type %d", get_active_function_name(TSRMLS_C), php_sock->type); RETURN_FALSE; } RETURN_LONG(retval);}/* }}} *//* {{{ proto int socket_sendto(resource socket, string buf, int len, int flags, string addr [, int port]) Sends a message to a socket, whether it is connected or not */PHP_FUNCTION(socket_sendto){ zval *arg1; php_socket *php_sock; struct sockaddr_un s_un; struct sockaddr_in sin; int retval, buf_len, addr_len; long len, flags, port = 0; char *buf, *addr; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rslls|l", &arg1, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port) == FAILURE) return; ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); switch (php_sock->type) { case AF_UNIX: memset(&s_un, 0, sizeof(s_un)); s_un.sun_family = AF_UNIX; snprintf(s_un.sun_path, 108, "%s", addr); retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &s_un, SUN_LEN(&s_un)); break; case AF_INET: if (ZEND_NUM_ARGS() != 6) { WRONG_PARAM_COUNT; } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons((unsigned short) port); if (! php_set_inet_addr(&sin, addr, php_sock TSRMLS_CC)) { RETURN_FALSE; } retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &sin, sizeof(sin)); break; default: php_error(E_WARNING, "%s() Unsupported socket type %d", get_active_function_name(TSRMLS_C), php_sock->type); RETURN_FALSE; } if (retval == -1) { PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno); RETURN_FALSE; } RETURN_LONG(retval);}/* }}} *//* {{{ proto bool socket_recvmsg(resource socket, resource iovec, array &control, int &controllen, int &flags, string &addr [, int &port]) Used to receive messages on a socket, whether connection-oriented or not */#ifdef HAVE_CMSGHDRPHP_FUNCTION(socket_recvmsg){ zval *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7 = NULL; php_iovec_t *iov; struct msghdr hdr; php_sockaddr_storage sa_storage; php_socket *php_sock; struct cmsghdr *ctl_buf; struct sockaddr *sa = (struct sockaddr *) &sa_storage;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -