static inline int sock_recvfrom(php_netstream_data_t *sock, char *buf, size_t buflen, int flags, zend_string **textaddr, struct sockaddr **addr, socklen_t *addrlen ) { int ret; int want_addr = textaddr || addr; if (want_addr) { php_sockaddr_storage sa; socklen_t sl = sizeof(sa); ret = recvfrom(sock->socket, buf, XP_SOCK_BUF_SIZE(buflen), flags, (struct sockaddr*)&sa, &sl); ret = (ret == SOCK_CONN_ERR) ? -1 : ret; if (sl) { php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl, textaddr, addr, addrlen); } else { if (textaddr) { *textaddr = ZSTR_EMPTY_ALLOC(); } if (addr) { *addr = NULL; *addrlen = 0; } } } else { ret = recv(sock->socket, buf, XP_SOCK_BUF_SIZE(buflen), flags); ret = (ret == SOCK_CONN_ERR) ? -1 : ret; } return ret; }
static inline int sock_sendto(php_netstream_data_t *sock, const char *buf, size_t buflen, int flags, struct sockaddr *addr, socklen_t addrlen ) { int ret; if (addr) { ret = sendto(sock->socket, buf, XP_SOCK_BUF_SIZE(buflen), flags, addr, XP_SOCK_BUF_SIZE(addrlen)); return (ret == SOCK_CONN_ERR) ? -1 : ret; } #ifdef PHP_WIN32 return ((ret = send(sock->socket, buf, buflen > INT_MAX ? INT_MAX : (int)buflen, flags)) == SOCK_CONN_ERR) ? -1 : ret; #else return ((ret = send(sock->socket, buf, buflen, flags)) == SOCK_CONN_ERR) ? -1 : ret; #endif }
static size_t php_sockop_read(php_stream *stream, char *buf, size_t count) { php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; ssize_t nr_bytes = 0; int err; if (!sock || sock->socket == -1) { return 0; } if (sock->is_blocked) { php_sock_stream_wait_for_data(stream, sock); if (sock->timeout_event) return 0; } nr_bytes = recv(sock->socket, buf, XP_SOCK_BUF_SIZE(count), (sock->is_blocked && sock->timeout.tv_sec != -1) ? MSG_DONTWAIT : 0); err = php_socket_errno(); stream->eof = (nr_bytes == 0 || (nr_bytes == -1 && err != EWOULDBLOCK && err != EAGAIN)); if (nr_bytes > 0) { php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0); } if (nr_bytes < 0) { nr_bytes = 0; } return nr_bytes; }
/* {{{ Generic socket stream operations */ static size_t php_sockop_write(php_stream *stream, const char *buf, size_t count) { php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; int didwrite; struct timeval *ptimeout; if (!sock || sock->socket == -1) { return 0; } if (sock->timeout.tv_sec == -1) ptimeout = NULL; else ptimeout = &sock->timeout; retry: didwrite = send(sock->socket, buf, XP_SOCK_BUF_SIZE(count), (sock->is_blocked && ptimeout) ? MSG_DONTWAIT : 0); if (didwrite <= 0) { int err = php_socket_errno(); char *estr; if (sock->is_blocked && (err == EWOULDBLOCK || err == EAGAIN)) { int retval; sock->timeout_event = 0; do { retval = php_pollfd_for(sock->socket, POLLOUT, ptimeout); if (retval == 0) { sock->timeout_event = 1; break; } if (retval > 0) { /* writable now; retry */ goto retry; } err = php_socket_errno(); } while (err == EINTR); } estr = php_socket_strerror(err, NULL, 0); php_error_docref(NULL, E_NOTICE, "send of " ZEND_LONG_FMT " bytes failed with errno=%ld %s", (zend_long)count, err, estr); efree(estr); } if (didwrite > 0) { php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), didwrite, 0); } if (didwrite < 0) { didwrite = 0; } return didwrite; }