@@ -579,39 +579,66 @@ void php_swoole_thread_bailout() {
579579 zend_bailout ();
580580}
581581
582- int php_swoole_thread_stream_cast (zval *zstream) {
582+ static swSocketFd php_swoole_thread_socket_dup (swSocketFd sockfd) {
583+ #ifdef _WIN32
584+ WSAPROTOCOL_INFOW protocol_info;
585+ if (WSADuplicateSocketW (sockfd, GetCurrentProcessId (), &protocol_info) != 0 ) {
586+ errno = sw_socket_errno ();
587+ return SW_BAD_SOCKET ;
588+ }
589+ swSocketFd newfd = WSASocketW (
590+ FROM_PROTOCOL_INFO , FROM_PROTOCOL_INFO , FROM_PROTOCOL_INFO , &protocol_info, 0 , WSA_FLAG_OVERLAPPED );
591+ if (newfd == SW_BAD_SOCKET ) {
592+ errno = sw_socket_errno ();
593+ }
594+ return newfd;
595+ #else
596+ return dup (sockfd);
597+ #endif
598+ }
599+
600+ swSocketFd php_swoole_thread_stream_cast (zval *zstream) {
583601 php_stream *stream;
584- int sockfd;
585- int cast_flags = PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL ;
602+ php_socket_t sockfd = SW_BAD_SOCKET ;
603+ int cast_flags = PHP_STREAM_AS_SOCKETD | PHP_STREAM_CAST_INTERNAL ;
586604 if ((php_stream_from_zval_no_verify (stream, zstream))) {
587- if (php_stream_cast (stream, cast_flags, (void **) &sockfd, 1 ) == SUCCESS && sockfd >= 0 ) {
588- return dup (sockfd);
605+ if (php_stream_cast (stream, cast_flags, (void **) &sockfd, 1 ) == SUCCESS && sockfd != SW_BAD_SOCKET ) {
606+ return php_swoole_thread_socket_dup (sockfd);
589607 }
590608 }
591- return - 1 ;
609+ return SW_BAD_SOCKET ;
592610}
593611
594- int php_swoole_thread_co_socket_cast (zval *zvalue, swSocketType *type) {
612+ swSocketFd php_swoole_thread_co_socket_cast (zval *zvalue, swSocketType *type) {
595613 SocketImpl *socket = php_swoole_get_socket (zvalue);
596614 if (!socket) {
597- return - 1 ;
615+ return SW_BAD_SOCKET ;
598616 }
599- int sockfd = socket->get_fd ();
600- if (sockfd < 0 ) {
601- return - 1 ;
617+ swSocketFd sockfd = socket->get_fd ();
618+ if (sockfd == SW_BAD_SOCKET ) {
619+ return SW_BAD_SOCKET ;
602620 }
603- int newfd = dup (sockfd);
604- if (newfd < 0 ) {
605- return - 1 ;
621+ swSocketFd newfd = php_swoole_thread_socket_dup (sockfd);
622+ if (newfd == SW_BAD_SOCKET ) {
623+ return SW_BAD_SOCKET ;
606624 }
607625 *type = socket->get_type ();
608626 return newfd;
609627}
610628
611- void php_swoole_thread_stream_create (zval *return_value, zend_long sockfd) {
629+ void php_swoole_thread_stream_create (zval *return_value, swSocketFd sockfd) {
630+ #ifdef _WIN32
631+ swSocketFd newfd = php_swoole_thread_socket_dup (sockfd);
632+ php_stream *stream =
633+ newfd == SW_BAD_SOCKET ? nullptr : php_stream_sock_open_from_socket ((php_socket_t ) newfd, nullptr );
634+ if (!stream && newfd != SW_BAD_SOCKET ) {
635+ sw_close_socket (newfd);
636+ }
637+ #else
612638 std::string path = " php://fd/" + std::to_string (sockfd);
613639 // The file descriptor will be duplicated once here
614640 php_stream *stream = php_stream_open_wrapper_ex (path.c_str (), " " , 0 , NULL , NULL );
641+ #endif
615642 if (stream) {
616643 php_stream_to_zval (stream, return_value);
617644 } else {
@@ -620,8 +647,8 @@ void php_swoole_thread_stream_create(zval *return_value, zend_long sockfd) {
620647 }
621648}
622649
623- void php_swoole_thread_co_socket_create (zval *return_value, zend_long sockfd, swSocketType type) {
624- swSocketFd newfd = (swSocketFd) dup (( int ) sockfd);
650+ void php_swoole_thread_co_socket_create (zval *return_value, swSocketFd sockfd, swSocketType type) {
651+ swSocketFd newfd = php_swoole_thread_socket_dup ( sockfd);
625652 if (newfd == SW_BAD_SOCKET ) {
626653 _error:
627654 object_init_ex (return_value, swoole_thread_error_ce);
@@ -637,17 +664,18 @@ void php_swoole_thread_co_socket_create(zval *return_value, zend_long sockfd, sw
637664}
638665
639666#ifdef SWOOLE_SOCKETS_SUPPORT
640- void php_swoole_thread_php_socket_create (zval *return_value, zend_long sockfd) {
641- int newfd = dup (sockfd);
642- if (newfd < 0 ) {
667+ void php_swoole_thread_php_socket_create (zval *return_value, swSocketFd sockfd) {
668+ swSocketFd newfd = php_swoole_thread_socket_dup (sockfd);
669+ if (newfd == SW_BAD_SOCKET ) {
643670 _error:
644671 object_init_ex (return_value, swoole_thread_error_ce);
645672 zend::object_set (return_value, ZEND_STRL (" code" ), errno);
646673 return ;
647674 }
648675 object_init_ex (return_value, socket_ce);
649676 auto retsock = Z_SOCKET_P (return_value);
650- if (!socket_import_file_descriptor (newfd, retsock)) {
677+ if (!socket_import_file_descriptor ((php_socket_t ) newfd, retsock)) {
678+ sw_close_socket (newfd);
651679 goto _error;
652680 }
653681}
@@ -696,7 +724,7 @@ void ArrayItem::store(zval *zvalue) {
696724 case IS_RESOURCE : {
697725 value.socket .fd = php_swoole_thread_stream_cast (zvalue);
698726 type = IS_STREAM_SOCKET ;
699- if (value.socket .fd == - 1 ) {
727+ if (value.socket .fd == SW_BAD_SOCKET ) {
700728 zend_throw_exception (swoole_exception_ce, " failed to convert to socket fd" , errno);
701729 }
702730 break ;
@@ -710,7 +738,7 @@ void ArrayItem::store(zval *zvalue) {
710738 if (sw_zval_is_co_socket (zvalue)) {
711739 value.socket .fd = php_swoole_thread_co_socket_cast (zvalue, &value.socket .type );
712740 type = IS_CO_SOCKET ;
713- if (value.socket .fd == - 1 ) {
741+ if (value.socket .fd == SW_BAD_SOCKET ) {
714742 zend_throw_exception (swoole_exception_ce, " failed to convert to socket fd" , errno);
715743 }
716744 break ;
@@ -722,8 +750,8 @@ void ArrayItem::store(zval *zvalue) {
722750 zend_throw_exception (swoole_exception_ce, " invalid socket fd" , EBADF );
723751 break ;
724752 }
725- value.socket .fd = dup (php_sock->bsd_socket );
726- if (value.socket .fd == - 1 ) {
753+ value.socket .fd = php_swoole_thread_socket_dup (php_sock->bsd_socket );
754+ if (value.socket .fd == SW_BAD_SOCKET ) {
727755 zend_throw_exception (swoole_exception_ce, " failed to dup socket fd" , errno);
728756 }
729757 type = IS_PHP_SOCKET ;
@@ -971,8 +999,8 @@ void ArrayItem::release() {
971999 zend_string_release (value.str );
9721000 value.str = nullptr ;
9731001 } else if (type == IS_STREAM_SOCKET || type == IS_CO_SOCKET || type == IS_PHP_SOCKET ) {
974- close (value.socket .fd );
975- value.socket .fd = - 1 ;
1002+ sw_close_socket (value.socket .fd );
1003+ value.socket .fd = SW_BAD_SOCKET ;
9761004 } else if (type == IS_SERIALIZED_OBJECT ) {
9771005 zend_string_release (value.serialized_object );
9781006 value.serialized_object = nullptr ;
0 commit comments