Skip to content

Commit 9c7497f

Browse files
committed
php#53: Add async support for UDP socket operations
Extend network_async functionality to UDP send/recv operations: * sock_sendto() now supports async writes with poll-first approach * sock_recvfrom() now supports async reads with poll-first approach * Consistent with existing TCP async implementation * Uses network_async_await_stream_socket() for efficient polling * Maintains backward compatibility for non-async contexts This enables UDP sockets to work seamlessly in async/coroutine environments without blocking the event loop.
1 parent 7dff544 commit 9c7497f

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

main/streams/xp_socket.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,24 @@ static inline int sock_sendto(php_netstream_data_t *sock, const char *buf, size_
353353
)
354354
{
355355
int ret;
356+
357+
if (ZEND_ASYNC_IS_ACTIVE && sock && sock->is_blocked && !sock->nonblocking_applied) {
358+
network_async_set_socket_blocking(sock->socket, false, sock);
359+
if (UNEXPECTED(EG(exception) != NULL)) {
360+
return -1;
361+
}
362+
}
363+
364+
/* Poll-first approach for writes - wait for socket writability */
365+
if (sock && sock->is_blocked && ZEND_ASYNC_IS_ACTIVE) {
366+
struct timeval *timeout = (sock->timeout.tv_sec == -1) ? NULL : &sock->timeout;
367+
int poll_result = network_async_await_stream_socket(sock, POLLOUT, timeout);
368+
if (poll_result <= 0) {
369+
/* Timeout or error during poll */
370+
return poll_result;
371+
}
372+
}
373+
356374
if (addr) {
357375
ret = sendto(sock->socket, buf, XP_SOCK_BUF_SIZE(buflen), flags, addr, XP_SOCK_BUF_SIZE(addrlen));
358376

@@ -373,6 +391,23 @@ static inline int sock_recvfrom(php_netstream_data_t *sock, char *buf, size_t bu
373391
int ret;
374392
int want_addr = textaddr || addr;
375393

394+
if (ZEND_ASYNC_IS_ACTIVE && sock && sock->is_blocked && !sock->nonblocking_applied) {
395+
network_async_set_socket_blocking(sock->socket, false, sock);
396+
if (UNEXPECTED(EG(exception) != NULL)) {
397+
return -1;
398+
}
399+
}
400+
401+
/* Poll-first approach for reads - wait for data availability */
402+
if (sock && sock->is_blocked && ZEND_ASYNC_IS_ACTIVE) {
403+
struct timeval *timeout = (sock->timeout.tv_sec == -1) ? NULL : &sock->timeout;
404+
int poll_result = network_async_await_stream_socket(sock, PHP_POLLREADABLE, timeout);
405+
if (poll_result <= 0) {
406+
/* Timeout or error during poll */
407+
return poll_result;
408+
}
409+
}
410+
376411
if (want_addr) {
377412
php_sockaddr_storage sa;
378413
socklen_t sl = sizeof(sa);

0 commit comments

Comments
 (0)