@@ -448,6 +448,109 @@ static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_hea
448
448
}
449
449
/* }}} */
450
450
451
+ /* {{{ */
452
+ PHP_FUNCTION (curl_multi_socket_action )
453
+ {
454
+ zval * z_mh ;
455
+ zval * z_socket ;
456
+ zend_long ev_bitmask ;
457
+ zval * z_still_running ;
458
+
459
+ ZEND_PARSE_PARAMETERS_START (4 ,4 )
460
+ Z_PARAM_OBJECT_OF_CLASS (z_mh , curl_multi_ce )
461
+ Z_PARAM_ZVAL (z_socket )
462
+ Z_PARAM_LONG (ev_bitmask )
463
+ Z_PARAM_ZVAL (z_still_running )
464
+ ZEND_PARSE_PARAMETERS_END ();
465
+
466
+ php_curlm * mh = Z_CURL_MULTI_P (z_mh );
467
+
468
+ curl_socket_t socket ;
469
+
470
+ if (Z_TYPE_P (z_socket ) == IS_LONG ) {
471
+ socket = (curl_socket_t ) Z_LVAL_P (z_socket );
472
+ } else {
473
+ php_stream * p_stream ;
474
+ php_stream_from_zval (p_stream , z_socket );
475
+ if (php_stream_cast (
476
+ p_stream , PHP_STREAM_AS_FD ,
477
+ (void * * ) & socket , REPORT_ERRORS ) != SUCCESS ) {
478
+ return ;
479
+ }
480
+ }
481
+
482
+ int still_running = zval_get_long (z_still_running );
483
+ CURLMcode error = curl_multi_socket_action (
484
+ mh -> multi , socket , ev_bitmask , & still_running );
485
+ ZEND_TRY_ASSIGN_REF_LONG (z_still_running , still_running );
486
+
487
+ SAVE_CURLM_ERROR (mh , error );
488
+ RETURN_LONG ((zend_long ) error );
489
+ }
490
+
491
+ static int _php_curl_multi_timerfunction (CURLM * multi , zend_long timeout , void * userp ) {
492
+ php_curlm * mh = (php_curlm * ) userp ;
493
+
494
+ zval z_object ;
495
+ ZVAL_OBJ_COPY (& z_object , & mh -> std );
496
+
497
+ zval z_timeout ;
498
+ ZVAL_LONG (& z_timeout , timeout );
499
+
500
+ zval call_args [2 ] = {z_object , z_timeout };
501
+ zval retval ;
502
+ zend_call_known_fcc (& mh -> handlers .timer_function , & retval , /* param_count */ 2 , call_args , /* named_params */ NULL );
503
+
504
+ if (!Z_ISUNDEF (retval )) {
505
+ zval_ptr_dtor (& retval );
506
+ }
507
+
508
+ zval_ptr_dtor (& z_object );
509
+ return SUCCESS ;
510
+ }
511
+
512
+ static int _php_curl_multi_socketfunction (CURL * easy , curl_socket_t socket , int what , void * userp , void * stream ) {
513
+ php_curlm * mh = (php_curlm * ) userp ;
514
+ php_stream * p_stream ;
515
+
516
+ if (stream == NULL && what != CURL_POLL_REMOVE ) {
517
+ p_stream = (void * ) php_stream_fopen_from_fd (socket , "rw" , NULL );
518
+ if (!p_stream ) {
519
+ return FAILURE ;
520
+ }
521
+
522
+ if (curl_multi_assign (mh -> multi , socket , p_stream ) != CURLM_OK ) {
523
+ php_stream_close (p_stream );
524
+ return FAILURE ;
525
+ }
526
+ } else {
527
+ p_stream = (php_stream * ) stream ;
528
+ }
529
+
530
+ zval z_stream ;
531
+ php_stream_to_zval (p_stream , & z_stream );
532
+
533
+ zval * z_easy = _php_curl_multi_find_easy_handle (mh , easy );
534
+
535
+ zval z_what ;
536
+ ZVAL_LONG (& z_what , what );
537
+ zval call_args [3 ] = {* z_easy , z_stream , z_what };
538
+ zval retval ;
539
+ zend_call_known_fcc (& mh -> handlers .socket_function , & retval , /* param_count */ 3 , call_args , /* named_params */ NULL );
540
+
541
+ if (!Z_ISUNDEF (retval )) {
542
+ zval_ptr_dtor (& retval );
543
+ }
544
+
545
+ if (what == CURL_POLL_REMOVE && p_stream != NULL ) {
546
+ curl_multi_assign (mh -> multi , socket , NULL );
547
+ php_stream_close (p_stream );
548
+ }
549
+
550
+ return SUCCESS ;
551
+ }
552
+ /* }}} */
553
+
451
554
static bool _php_curl_multi_setopt (php_curlm * mh , zend_long option , zval * zvalue , zval * return_value ) /* {{{ */
452
555
{
453
556
CURLMcode error = CURLM_OK ;
@@ -499,6 +602,49 @@ static bool _php_curl_multi_setopt(php_curlm *mh, zend_long option, zval *zvalue
499
602
error = curl_multi_setopt (mh -> multi , CURLMOPT_PUSHDATA , mh );
500
603
break ;
501
604
}
605
+ case CURLMOPT_SOCKETFUNCTION : {
606
+ if (ZEND_FCC_INITIALIZED (mh -> handlers .socket_function )) {
607
+ zend_fcc_dtor (& mh -> handlers .socket_function );
608
+ }
609
+
610
+ char * error_str = NULL ;
611
+ if (UNEXPECTED (!zend_is_callable_ex (zvalue , /* object */ NULL , /* check_flags */ 0 , /* callable_name */ NULL , & mh -> handlers .socket_function , /* error */ & error_str ))) {
612
+ if (!EG (exception )) {
613
+ zend_argument_type_error (2 , "must be a valid callback for option CURLMOPT_SOCKETFUNCTION, %s" , error_str );
614
+ }
615
+ efree (error_str );
616
+ return false;
617
+ }
618
+ zend_fcc_addref (& mh -> handlers .socket_function );
619
+
620
+ error = curl_multi_setopt (mh -> multi , CURLMOPT_SOCKETFUNCTION , _php_curl_multi_socketfunction );
621
+ if (error != CURLM_OK ) {
622
+ return false;
623
+ }
624
+ error = curl_multi_setopt (mh -> multi , CURLMOPT_SOCKETDATA , mh );
625
+ break ;
626
+ }
627
+ case CURLMOPT_TIMERFUNCTION : {
628
+ if (ZEND_FCC_INITIALIZED (mh -> handlers .timer_function )) {
629
+ zend_fcc_dtor (& mh -> handlers .timer_function );
630
+ }
631
+
632
+ char * error_str = NULL ;
633
+ if (UNEXPECTED (!zend_is_callable_ex (zvalue , /* object */ NULL , /* check_flags */ 0 , /* callable_name */ NULL , & mh -> handlers .timer_function , /* error */ & error_str ))) {
634
+ if (!EG (exception )) {
635
+ zend_argument_type_error (2 , "must be a valid callback for option CURLMOPT_TIMERFUNCTION, %s" , error_str );
636
+ }
637
+ efree (error_str );
638
+ return false;
639
+ }
640
+ zend_fcc_addref (& mh -> handlers .timer_function );
641
+ error = curl_multi_setopt (mh -> multi , CURLMOPT_TIMERFUNCTION , _php_curl_multi_timerfunction );
642
+ if (error != CURLM_OK ) {
643
+ return false;
644
+ }
645
+ error = curl_multi_setopt (mh -> multi , CURLMOPT_TIMERDATA , mh );
646
+ break ;
647
+ }
502
648
default :
503
649
zend_argument_value_error (2 , "is not a valid cURL multi option" );
504
650
error = CURLM_UNKNOWN_OPTION ;
@@ -575,6 +721,14 @@ static void curl_multi_free_obj(zend_object *object)
575
721
zend_fcc_dtor (& mh -> handlers .server_push );
576
722
}
577
723
724
+ if (ZEND_FCC_INITIALIZED (mh -> handlers .timer_function )) {
725
+ zend_fcc_dtor (& mh -> handlers .timer_function );
726
+ }
727
+
728
+ if (ZEND_FCC_INITIALIZED (mh -> handlers .socket_function )) {
729
+ zend_fcc_dtor (& mh -> handlers .socket_function );
730
+ }
731
+
578
732
zend_object_std_dtor (& mh -> std );
579
733
}
580
734
@@ -588,6 +742,14 @@ static HashTable *curl_multi_get_gc(zend_object *object, zval **table, int *n)
588
742
zend_get_gc_buffer_add_fcc (gc_buffer , & curl_multi -> handlers .server_push );
589
743
}
590
744
745
+ if (ZEND_FCC_INITIALIZED (curl_multi -> handlers .timer_function )) {
746
+ zend_get_gc_buffer_add_fcc (gc_buffer , & curl_multi -> handlers .timer_function );
747
+ }
748
+
749
+ if (ZEND_FCC_INITIALIZED (curl_multi -> handlers .socket_function )) {
750
+ zend_get_gc_buffer_add_fcc (gc_buffer , & curl_multi -> handlers .socket_function );
751
+ }
752
+
591
753
zend_llist_position pos ;
592
754
for (zval * pz_ch = (zval * ) zend_llist_get_first_ex (& curl_multi -> easyh , & pos ); pz_ch ;
593
755
pz_ch = (zval * ) zend_llist_get_next_ex (& curl_multi -> easyh , & pos )) {
0 commit comments