[PECL-CVS] [pecl-networking-gearman] add-ssl-support: Add SSL support

[email protected] (Rasmus Lerdorf) Sat, 4 Apr 2026 18:32:08 +0000
Newsgroups php.pecl.cvs
Message-ID <[email protected]>
Author: Rasmus Lerdorf (rlerdorf)
Date: 2026-04-04T14:31:43-04:00

Commit: https://github.com/php/pecl-networking-gearman/commit/d8b52e5fc63be071efe96d45eac2e67fc2262eaa
Raw diff: https://github.com/php/pecl-networking-gearman/commit/d8b52e5fc63be071efe96d45eac2e67fc2262eaa.diff

Add SSL support

Changed paths:
  A  tests/gearman_client_024.phpt
  A  tests/gearman_worker_020.phpt
  M  config.m4
  M  gearman_arginfo.h
  M  php_gearman_client.c
  M  php_gearman_worker.c


Diff:

diff --git a/config.m4 b/config.m4
index 5f427c7..db5930f 100644
--- a/config.m4
+++ b/config.m4
@@ -71,6 +71,20 @@ if test "$PHP_GEARMAN" != "no"; then
     -L$GEARMAN_LIB_DIR -R$GEARMAN_LIB_DIR
   ])
 
+  PHP_CHECK_LIBRARY(gearman, gearman_client_set_ssl,
+  [
+    AC_DEFINE(HAVE_GEARMAN_CLIENT_SET_SSL, 1, [Whether gearman_client_set_ssl is available])
+  ],[],[
+    -L$GEARMAN_LIB_DIR -R$GEARMAN_LIB_DIR
+  ])
+
+  PHP_CHECK_LIBRARY(gearman, gearman_worker_set_ssl,
+  [
+    AC_DEFINE(HAVE_GEARMAN_WORKER_SET_SSL, 1, [Whether gearman_worker_set_ssl is available])
+  ],[],[
+    -L$GEARMAN_LIB_DIR -R$GEARMAN_LIB_DIR
+  ])
+
   PHP_SUBST(GEARMAN_SHARED_LIBADD)
 
   PHP_ADD_INCLUDE($GEARMAN_INC_DIR)
diff --git a/gearman_arginfo.h b/gearman_arginfo.h
index 49c7a99..7f81b2e 100644
--- a/gearman_arginfo.h
+++ b/gearman_arginfo.h
@@ -46,6 +46,16 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gearman_client_set_timeout, 0, 2
 	ZEND_ARG_TYPE_INFO(0, timeout, IS_LONG, 0)
 ZEND_END_ARG_INFO()
 
+#ifdef HAVE_GEARMAN_CLIENT_SET_SSL
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gearman_client_set_ssl, 0, 1, _IS_BOOL, 0)
+	ZEND_ARG_OBJ_INFO(0, obj, GearmanClient, 0)
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ssl, _IS_BOOL, 0, "true")
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ca_file, IS_STRING, 1, "null")
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, certificate, IS_STRING, 1, "null")
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, key_file, IS_STRING, 1, "null")
+ZEND_END_ARG_INFO()
+#endif
+
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gearman_client_add_server, 0, 1, _IS_BOOL, 0)
 	ZEND_ARG_OBJ_INFO(0, obj, GearmanClient, 0)
 	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, host, IS_STRING, 1, "null")
@@ -280,6 +290,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gearman_worker_set_timeout, 0, 2
 	ZEND_ARG_TYPE_INFO(0, timeout, IS_LONG, 0)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gearman_worker_set_ssl, 0, 1, _IS_BOOL, 0)
+	ZEND_ARG_OBJ_INFO(0, obj, GearmanWorker, 0)
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ssl, _IS_BOOL, 0, "true")
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ca_file, IS_STRING, 1, "null")
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, certificate, IS_STRING, 1, "null")
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, key_file, IS_STRING, 1, "null")
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gearman_worker_set_id, 0, 2, _IS_BOOL, 0)
 	ZEND_ARG_OBJ_INFO(0, obj, GearmanWorker, 0)
 	ZEND_ARG_TYPE_INFO(0, id, IS_STRING, 0)
@@ -365,6 +383,15 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_GearmanClient_setTimeout,
 	ZEND_ARG_TYPE_INFO(0, timeout, IS_LONG, 0)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_GearmanClient_setSSL, 0, 0, _IS_BOOL, 0)
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ssl, _IS_BOOL, 0, "true")
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ca_file, IS_STRING, 1, "null")
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, certificate, IS_STRING, 1, "null")
+	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, key_file, IS_STRING, 1, "null")
+ZEND_END_ARG_INFO()
+
+#define arginfo_class_GearmanWorker_setSSL arginfo_class_GearmanClient_setSSL
+
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_GearmanClient_addServer, 0, 0, _IS_BOOL, 0)
 	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, host, IS_STRING, 1, "null")
 	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "0")
@@ -613,6 +640,9 @@ ZEND_FUNCTION(gearman_client_add_options);
 ZEND_FUNCTION(gearman_client_remove_options);
 ZEND_FUNCTION(gearman_client_timeout);
 ZEND_FUNCTION(gearman_client_set_timeout);
+#ifdef HAVE_GEARMAN_CLIENT_SET_SSL
+ZEND_FUNCTION(gearman_client_set_ssl);
+#endif
 ZEND_FUNCTION(gearman_client_add_server);
 ZEND_FUNCTION(gearman_client_add_servers);
 ZEND_FUNCTION(gearman_client_wait);
@@ -681,6 +711,7 @@ ZEND_FUNCTION(gearman_worker_add_options);
 ZEND_FUNCTION(gearman_worker_remove_options);
 ZEND_FUNCTION(gearman_worker_timeout);
 ZEND_FUNCTION(gearman_worker_set_timeout);
+ZEND_FUNCTION(gearman_worker_set_ssl);
 ZEND_FUNCTION(gearman_worker_set_id);
 ZEND_FUNCTION(gearman_worker_add_server);
 ZEND_FUNCTION(gearman_worker_add_servers);
@@ -716,6 +747,9 @@ static const zend_function_entry ext_functions[] = {
 	ZEND_FE(gearman_client_remove_options, arginfo_gearman_client_remove_options)
 	ZEND_FE(gearman_client_timeout, arginfo_gearman_client_timeout)
 	ZEND_FE(gearman_client_set_timeout, arginfo_gearman_client_set_timeout)
+#ifdef HAVE_GEARMAN_CLIENT_SET_SSL
+	ZEND_FE(gearman_client_set_ssl, arginfo_gearman_client_set_ssl)
+#endif
 	ZEND_FE(gearman_client_add_server, arginfo_gearman_client_add_server)
 	ZEND_FE(gearman_client_add_servers, arginfo_gearman_client_add_servers)
 	ZEND_FE(gearman_client_wait, arginfo_gearman_client_wait)
@@ -784,6 +818,7 @@ static const zend_function_entry ext_functions[] = {
 	ZEND_FE(gearman_worker_remove_options, arginfo_gearman_worker_remove_options)
 	ZEND_FE(gearman_worker_timeout, arginfo_gearman_worker_timeout)
 	ZEND_FE(gearman_worker_set_timeout, arginfo_gearman_worker_set_timeout)
+	ZEND_FE(gearman_worker_set_ssl, arginfo_gearman_worker_set_ssl)
 	ZEND_FE(gearman_worker_set_id, arginfo_gearman_worker_set_id)
 	ZEND_FE(gearman_worker_add_server, arginfo_gearman_worker_add_server)
 	ZEND_FE(gearman_worker_add_servers, arginfo_gearman_worker_add_servers)
@@ -812,6 +847,9 @@ static const zend_function_entry class_GearmanClient_methods[] = {
 	ZEND_ME_MAPPING(removeOptions, gearman_client_remove_options, arginfo_class_GearmanClient_removeOptions, ZEND_ACC_PUBLIC)
 	ZEND_ME_MAPPING(timeout, gearman_client_timeout, arginfo_class_GearmanClient_timeout, ZEND_ACC_PUBLIC)
 	ZEND_ME_MAPPING(setTimeout, gearman_client_set_timeout, arginfo_class_GearmanClient_setTimeout, ZEND_ACC_PUBLIC)
+#ifdef HAVE_GEARMAN_CLIENT_SET_SSL
+	ZEND_ME_MAPPING(setSSL, gearman_client_set_ssl, arginfo_class_GearmanClient_setSSL, ZEND_ACC_PUBLIC)
+#endif
 	ZEND_ME_MAPPING(addServer, gearman_client_add_server, arginfo_class_GearmanClient_addServer, ZEND_ACC_PUBLIC)
 	ZEND_ME_MAPPING(addServers, gearman_client_add_servers, arginfo_class_GearmanClient_addServers, ZEND_ACC_PUBLIC)
 	ZEND_ME_MAPPING(wait, gearman_client_wait, arginfo_class_GearmanClient_wait, ZEND_ACC_PUBLIC)
@@ -899,6 +937,7 @@ static const zend_function_entry class_GearmanWorker_methods[] = {
 	ZEND_ME_MAPPING(removeOptions, gearman_worker_remove_options, arginfo_class_GearmanWorker_removeOptions, ZEND_ACC_PUBLIC)
 	ZEND_ME_MAPPING(timeout, gearman_worker_timeout, arginfo_class_GearmanWorker_timeout, ZEND_ACC_PUBLIC)
 	ZEND_ME_MAPPING(setTimeout, gearman_worker_set_timeout, arginfo_class_GearmanWorker_setTimeout, ZEND_ACC_PUBLIC)
+	ZEND_ME_MAPPING(setSSL, gearman_worker_set_ssl, arginfo_class_GearmanWorker_setSSL, ZEND_ACC_PUBLIC)
 	ZEND_ME_MAPPING(setId, gearman_worker_set_id, arginfo_class_GearmanWorker_setId, ZEND_ACC_PUBLIC)
 	ZEND_ME_MAPPING(addServer, gearman_worker_add_server, arginfo_class_GearmanWorker_addServer, ZEND_ACC_PUBLIC)
 	ZEND_ME_MAPPING(addServers, gearman_worker_add_servers, arginfo_class_GearmanWorker_addServers, ZEND_ACC_PUBLIC)
diff --git a/php_gearman_client.c b/php_gearman_client.c
index 5a30ed1..7767b7e 100644
--- a/php_gearman_client.c
+++ b/php_gearman_client.c
@@ -9,6 +9,10 @@
  * the LICENSE file in this directory for full text.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "php_gearman_task.h"
 #include "php_gearman_client.h"
 
@@ -271,6 +275,47 @@ PHP_FUNCTION(gearman_client_set_timeout) {
 }
 /* }}} */
 
+#ifdef HAVE_GEARMAN_CLIENT_SET_SSL
+/* {{{ proto bool gearman_client_set_ssl(object client [, bool ssl [, string ca_file [, string certificate [, string key_file ]]]])
+   Set SSL for a client structure. */
+PHP_FUNCTION(gearman_client_set_ssl) {
+        zend_bool ssl = 1;
+        char *ca_file = NULL;
+        size_t ca_file_len = 0;
+        char *certificate = NULL;
+        size_t certificate_len = 0;
+        char *key_file = NULL;
+        size_t key_file_len = 0;
+
+        gearman_client_obj *obj;
+        zval *zobj;
+
+        if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|bsss",
+                                        &zobj, gearman_client_ce,
+                                        &ssl,
+                                        &ca_file, &ca_file_len,
+                                        &certificate, &certificate_len,
+                                        &key_file, &key_file_len) == FAILURE) {
+                RETURN_FALSE;
+        }
+        obj = Z_GEARMAN_CLIENT_P(zobj);
+
+        if (ca_file == NULL) {
+                cfg_get_string("gearman.ssl_ca_file", &ca_file);
+        }
+        if (certificate == NULL) {
+                cfg_get_string("gearman.ssl_certificate", &certificate);
+        }
+        if (key_file == NULL) {
+                cfg_get_string("gearman.ssl_key_file", &key_file);
+        }
+
+        gearman_client_set_ssl(&(obj->client), ssl, ca_file, certificate, key_file);
+        RETURN_TRUE;
+}
+/* }}} */
+#endif
+
 /* {{{ proto bool gearman_client_add_server(object client [, ?string host = null [, int port [, bool setupExceptionHandler ]]])
    Add a job server to a client. This goes into a list of servers than can be used to run tasks. No socket I/O happens here, it is just added to a list. */
 PHP_FUNCTION(gearman_client_add_server) {
diff --git a/php_gearman_worker.c b/php_gearman_worker.c
index 3263bea..2a29bff 100644
--- a/php_gearman_worker.c
+++ b/php_gearman_worker.c
@@ -9,6 +9,10 @@
  * the LICENSE file in this directory for full text.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "php_gearman_worker.h"
 
 gearman_worker_obj *gearman_worker_fetch_object(zend_object *obj) {
@@ -288,6 +292,66 @@ PHP_FUNCTION(gearman_worker_set_id) {
 }
 /* }}} */
 
+/* {{{ proto bool gearman_worker_set_ssl(object worker [, bool ssl [, string ca_file [, string certificate [, string key_file ]]]])
+   Set SSL for a worker structure. */
+PHP_FUNCTION(gearman_worker_set_ssl) {
+        zend_bool ssl = 1;
+        char *ca_file = NULL;
+        size_t ca_file_len = 0;
+        char *certificate = NULL;
+        size_t certificate_len = 0;
+        char *key_file = NULL;
+        size_t key_file_len = 0;
+
+        gearman_worker_obj *obj;
+        zval *zobj;
+
+        if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|bsss",
+                                        &zobj, gearman_worker_ce,
+                                        &ssl,
+                                        &ca_file, &ca_file_len,
+                                        &certificate, &certificate_len,
+                                        &key_file, &key_file_len) == FAILURE) {
+                RETURN_FALSE;
+        }
+        obj = Z_GEARMAN_WORKER_P(zobj);
+
+        if (ca_file == NULL) {
+                cfg_get_string("gearman.ssl_ca_file", &ca_file);
+        }
+        if (certificate == NULL) {
+                cfg_get_string("gearman.ssl_certificate", &certificate);
+        }
+        if (key_file == NULL) {
+                cfg_get_string("gearman.ssl_key_file", &key_file);
+        }
+
+#ifdef HAVE_GEARMAN_WORKER_SET_SSL
+        gearman_worker_set_ssl(&(obj->worker), ssl, ca_file, certificate, key_file);
+#else
+        /* gearman_worker_set_ssl() is declared in libgearman headers but not
+         * implemented (missing symbol). Use addOptions as fallback for the SSL
+         * flag, and set env vars for cert paths since that's how libgearman's
+         * internal SSL init reads them. */
+        if (ssl) {
+                gearman_worker_add_options(&(obj->worker), GEARMAN_WORKER_SSL);
+        } else {
+                gearman_worker_remove_options(&(obj->worker), GEARMAN_WORKER_SSL);
+        }
+        if (ca_file) {
+                setenv("GEARMAND_CA_CERTIFICATE", ca_file, 1);
+        }
+        if (certificate) {
+                setenv("GEARMAN_CLIENT_SSL_CERTIFICATE", certificate, 1);
+        }
+        if (key_file) {
+                setenv("GEARMAN_CLIENT_SSL_KEY", key_file, 1);
+        }
+#endif
+        RETURN_TRUE;
+}
+/* }}} */
+
 /* {{{ proto bool gearman_worker_add_server(object worker [, string host [, int port [, bool setupExceptionHandler = true]]])
    Add a job server to a worker. This goes into a list of servers than can be used to run tasks. No socket I/O happens here, it is just added to a list. */
 PHP_FUNCTION(gearman_worker_add_server) {
diff --git a/tests/gearman_client_024.phpt b/tests/gearman_client_024.phpt
new file mode 100644
index 0000000..28c14d9
--- /dev/null
+++ b/tests/gearman_client_024.phpt
@@ -0,0 +1,21 @@
+--TEST--
+GearmanClient::setSSL(), gearman_client_set_ssl()
+--SKIPIF--
+<?php
+if (!extension_loaded("gearman")) die("skip");
+if (!method_exists('GearmanClient', 'setSSL')) die("skip libgearman without SSL support");
+?>
+--FILE--
+<?php
+$client = new GearmanClient();
+var_dump($client->setSSL(false));
+
+$client2 = gearman_client_create();
+var_dump(gearman_client_set_ssl($client2, false));
+
+print "OK";
+?>
+--EXPECT--
+bool(true)
+bool(true)
+OK
diff --git a/tests/gearman_worker_020.phpt b/tests/gearman_worker_020.phpt
new file mode 100644
index 0000000..3ec7985
--- /dev/null
+++ b/tests/gearman_worker_020.phpt
@@ -0,0 +1,20 @@
+--TEST--
+GearmanWorker::setSSL(), gearman_worker_set_ssl()
+--SKIPIF--
+<?php
+if (!extension_loaded("gearman")) die("skip");
+?>
+--FILE--
+<?php
+$worker = new GearmanWorker();
+var_dump($worker->setSSL(false));
+
+$worker2 = gearman_worker_create();
+var_dump(gearman_worker_set_ssl($worker2, false));
+
+print "OK";
+?>
+--EXPECT--
+bool(true)
+bool(true)
+OK