blob: 8c7eaee203fbcab2cb1a99e23167ce15c97da2a9 [file] [log] [blame]
Craig Tiller1a61b172015-02-16 11:53:47 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Craig Tiller1a61b172015-02-16 11:53:47 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Craig Tiller1a61b172015-02-16 11:53:47 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Craig Tiller1a61b172015-02-16 11:53:47 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Craig Tiller1a61b172015-02-16 11:53:47 -080016 *
17 */
18
thinkerou771c2052018-05-15 10:37:43 +080019#include "server.h"
mlumishb892a272014-12-09 16:28:23 -080020
murgatroid998242ba72015-04-01 15:29:44 -070021#include <ext/spl/spl_exceptions.h>
murgatroid998242ba72015-04-01 15:29:44 -070022#include <zend_exceptions.h>
mlumishb892a272014-12-09 16:28:23 -080023
murgatroid998242ba72015-04-01 15:29:44 -070024#include <grpc/grpc_security.h>
Craig Tiller7c70b6c2017-01-23 07:48:42 -080025#include <grpc/slice.h>
26#include <grpc/support/alloc.h>
mlumishb892a272014-12-09 16:28:23 -080027
thinkerou771c2052018-05-15 10:37:43 +080028#include "call.h"
murgatroid99268acd52015-05-14 15:05:00 -070029#include "completion_queue.h"
mlumishb892a272014-12-09 16:28:23 -080030#include "channel.h"
31#include "server_credentials.h"
murgatroid99afd541c2015-03-03 18:16:09 -080032#include "timeval.h"
mlumishb892a272014-12-09 16:28:23 -080033
Xiaoguang Sun8a929a92015-03-13 14:22:31 +080034zend_class_entry *grpc_ce_server;
thinkeroufe037cb2018-05-16 12:51:28 +080035PHP_GRPC_DECLARE_OBJECT_HANDLER(server_ce_handlers)
Xiaoguang Sun8a929a92015-03-13 14:22:31 +080036
mlumishb892a272014-12-09 16:28:23 -080037/* Frees and destroys an instance of wrapped_grpc_server */
thinkerou011d1ef2016-07-27 09:44:49 +080038PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_server)
39 if (p->wrapped != NULL) {
40 grpc_server_shutdown_and_notify(p->wrapped, completion_queue, NULL);
41 grpc_server_cancel_all_calls(p->wrapped);
Craig Tiller143e7bf2015-07-13 08:41:49 -070042 grpc_completion_queue_pluck(completion_queue, NULL,
Nicolas "Pixel" Noble150b7c42015-08-01 01:15:10 +020043 gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
thinkerou011d1ef2016-07-27 09:44:49 +080044 grpc_server_destroy(p->wrapped);
mlumishb892a272014-12-09 16:28:23 -080045 }
thinkerou011d1ef2016-07-27 09:44:49 +080046PHP_GRPC_FREE_WRAPPED_FUNC_END()
47
thinkerou03dc2192016-08-16 19:31:44 +080048/* Initializes an instance of wrapped_grpc_call to be associated with an
49 * object of a class specified by class_type */
thinkeroudba5b0c2016-07-27 18:39:16 +080050php_grpc_zend_object create_wrapped_grpc_server(zend_class_entry *class_type
51 TSRMLS_DC) {
thinkerouba75c012016-07-28 02:30:08 +080052 PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_server);
mlumishb892a272014-12-09 16:28:23 -080053 zend_object_std_init(&intern->std, class_type TSRMLS_CC);
54 object_properties_init(&intern->std, class_type);
thinkeroudc673c52016-07-28 09:49:38 +080055 PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_server, server_ce_handlers);
thinkeroudba5b0c2016-07-27 18:39:16 +080056}
thinkeroua3730b72016-07-20 16:59:54 +080057
mlumishb892a272014-12-09 16:28:23 -080058/**
59 * Constructs a new instance of the Server class
thinkerouefbc9e72016-08-16 20:00:36 +080060 * @param array $args_array The arguments to pass to the server (optional)
mlumishb892a272014-12-09 16:28:23 -080061 */
Craig Tillerb5dcec52015-01-13 11:13:42 -080062PHP_METHOD(Server, __construct) {
thinkeroufe037cb2018-05-16 12:51:28 +080063 wrapped_grpc_server *server =
64 PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
mlumishb892a272014-12-09 16:28:23 -080065 zval *args_array = NULL;
66 grpc_channel_args args;
thinkeroua3730b72016-07-20 16:59:54 +080067
murgatroid991b027f52015-03-11 15:41:00 -070068 /* "|a" == 1 optional array */
69 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &args_array) ==
murgatroid99afd541c2015-03-03 18:16:09 -080070 FAILURE) {
mlumishb892a272014-12-09 16:28:23 -080071 zend_throw_exception(spl_ce_InvalidArgumentException,
thinkeroufe037cb2018-05-16 12:51:28 +080072 "Server expects an array", 1 TSRMLS_CC);
mlumishb892a272014-12-09 16:28:23 -080073 return;
74 }
mlumishb892a272014-12-09 16:28:23 -080075 if (args_array == NULL) {
Nicolas "Pixel" Noble150b7c42015-08-01 01:15:10 +020076 server->wrapped = grpc_server_create(NULL, NULL);
mlumishb892a272014-12-09 16:28:23 -080077 } else {
ncteisenbefcfee2018-08-15 15:26:54 -070078 if (php_grpc_read_args_array(args_array, &args TSRMLS_CC) == FAILURE) {
79 efree(args.args);
80 return;
81 }
Nicolas "Pixel" Noble150b7c42015-08-01 01:15:10 +020082 server->wrapped = grpc_server_create(&args, NULL);
mlumishb892a272014-12-09 16:28:23 -080083 efree(args.args);
84 }
Nicolas "Pixel" Noble150b7c42015-08-01 01:15:10 +020085 grpc_server_register_completion_queue(server->wrapped, completion_queue,
86 NULL);
mlumishb892a272014-12-09 16:28:23 -080087}
88
89/**
90 * Request a call on a server. Creates a single GRPC_SERVER_RPC_NEW event.
thinkerou03dc2192016-08-16 19:31:44 +080091 * @return void
mlumishb892a272014-12-09 16:28:23 -080092 */
murgatroid99c1d7e242015-04-02 10:02:43 -070093PHP_METHOD(Server, requestCall) {
mlumish8f911632015-01-02 13:34:14 -080094 grpc_call_error error_code;
murgatroid99afd541c2015-03-03 18:16:09 -080095 grpc_call *call;
96 grpc_call_details details;
97 grpc_metadata_array metadata;
Craig Tiller64be9f72015-05-04 14:53:51 -070098 grpc_event event;
thinkeroua3730b72016-07-20 16:59:54 +080099
thinkeroufe037cb2018-05-16 12:51:28 +0800100 wrapped_grpc_server *server =
101 PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
thinkeroua3730b72016-07-20 16:59:54 +0800102 zval *result;
thinkerou6f9d30b2016-07-27 03:19:03 +0800103 PHP_GRPC_MAKE_STD_ZVAL(result);
murgatroid99afd541c2015-03-03 18:16:09 -0800104 object_init(result);
thinkeroua3730b72016-07-20 16:59:54 +0800105
murgatroid99afd541c2015-03-03 18:16:09 -0800106 grpc_call_details_init(&details);
107 grpc_metadata_array_init(&metadata);
Craig Tillerf5081452015-05-06 12:42:47 -0700108 error_code =
thinkerou6bc4b2f2018-04-30 22:28:20 +0800109 grpc_server_request_call(server->wrapped, &call, &details, &metadata,
110 completion_queue, completion_queue, NULL);
murgatroid99afd541c2015-03-03 18:16:09 -0800111 if (error_code != GRPC_CALL_OK) {
112 zend_throw_exception(spl_ce_LogicException, "request_call failed",
113 (long)error_code TSRMLS_CC);
114 goto cleanup;
mlumishb892a272014-12-09 16:28:23 -0800115 }
Craig Tiller143e7bf2015-07-13 08:41:49 -0700116 event = grpc_completion_queue_pluck(completion_queue, NULL,
thinkeroua3730b72016-07-20 16:59:54 +0800117 gpr_inf_future(GPR_CLOCK_REALTIME),
118 NULL);
Craig Tiller64be9f72015-05-04 14:53:51 -0700119 if (!event.success) {
murgatroid99afd541c2015-03-03 18:16:09 -0800120 zend_throw_exception(spl_ce_LogicException,
121 "Failed to request a call for some reason",
122 1 TSRMLS_CC);
123 goto cleanup;
124 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800125 char *method_text = grpc_slice_to_c_string(details.method);
126 char *host_text = grpc_slice_to_c_string(details.host);
127 php_grpc_add_property_string(result, "method", method_text, true);
128 php_grpc_add_property_string(result, "host", host_text, true);
129 gpr_free(method_text);
130 gpr_free(host_text);
thinkerou6bc4b2f2018-04-30 22:28:20 +0800131 php_grpc_add_property_zval(result, "call",
132 grpc_php_wrap_call(call, true TSRMLS_CC));
133 php_grpc_add_property_zval(result, "absolute_deadline",
134 grpc_php_wrap_timeval(details.deadline TSRMLS_CC));
135 php_grpc_add_property_zval(result, "metadata",
136 grpc_parse_metadata_array(&metadata TSRMLS_CC));
thinkeroua3730b72016-07-20 16:59:54 +0800137
138 cleanup:
139 grpc_call_details_destroy(&details);
140 grpc_metadata_array_destroy(&metadata);
thinkerou6f9d30b2016-07-27 03:19:03 +0800141 RETURN_DESTROY_ZVAL(result);
mlumishb892a272014-12-09 16:28:23 -0800142}
143
144/**
145 * Add a http2 over tcp listener.
146 * @param string $addr The address to add
Ryan Gordon1c0a3362017-10-17 09:23:09 -0700147 * @return int Port on success, 0 on failure
mlumishb892a272014-12-09 16:28:23 -0800148 */
murgatroid99c1d7e242015-04-02 10:02:43 -0700149PHP_METHOD(Server, addHttp2Port) {
thinkeroua3730b72016-07-20 16:59:54 +0800150 const char *addr;
thinkerou19304682016-07-22 02:43:19 +0800151 php_grpc_int addr_len;
thinkeroufe037cb2018-05-16 12:51:28 +0800152 wrapped_grpc_server *server =
153 PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
thinkeroua3730b72016-07-20 16:59:54 +0800154
mlumishb892a272014-12-09 16:28:23 -0800155 /* "s" == 1 string */
thinkeroua3730b72016-07-20 16:59:54 +0800156 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len)
157 == FAILURE) {
mlumishb892a272014-12-09 16:28:23 -0800158 zend_throw_exception(spl_ce_InvalidArgumentException,
Craig Tillerb5dcec52015-01-13 11:13:42 -0800159 "add_http2_port expects a string", 1 TSRMLS_CC);
mlumishb892a272014-12-09 16:28:23 -0800160 return;
161 }
Craig Tillerc5ae3eb2015-08-03 10:42:22 -0700162 RETURN_LONG(grpc_server_add_insecure_http2_port(server->wrapped, addr));
mlumishb892a272014-12-09 16:28:23 -0800163}
164
thinkerou03dc2192016-08-16 19:31:44 +0800165/**
166 * Add a secure http2 over tcp listener.
167 * @param string $addr The address to add
168 * @param ServerCredentials The ServerCredentials object
Ryan Gordon1c0a3362017-10-17 09:23:09 -0700169 * @return int Port on success, 0 on failure
thinkerou03dc2192016-08-16 19:31:44 +0800170 */
murgatroid99c1d7e242015-04-02 10:02:43 -0700171PHP_METHOD(Server, addSecureHttp2Port) {
thinkeroua3730b72016-07-20 16:59:54 +0800172 const char *addr;
thinkerou19304682016-07-22 02:43:19 +0800173 php_grpc_int addr_len;
thinkeroua3730b72016-07-20 16:59:54 +0800174 zval *creds_obj;
thinkeroufe037cb2018-05-16 12:51:28 +0800175 wrapped_grpc_server *server =
176 PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
thinkeroua3730b72016-07-20 16:59:54 +0800177
murgatroid998b87e842015-03-04 12:14:53 -0800178 /* "sO" == 1 string, 1 object */
murgatroid991b027f52015-03-11 15:41:00 -0700179 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &addr, &addr_len,
murgatroid998b87e842015-03-04 12:14:53 -0800180 &creds_obj, grpc_ce_server_credentials) ==
Craig Tillerb5dcec52015-01-13 11:13:42 -0800181 FAILURE) {
thinkerou6bc4b2f2018-04-30 22:28:20 +0800182 zend_throw_exception(spl_ce_InvalidArgumentException,
183 "add_http2_port expects a string and a "
184 "ServerCredentials", 1 TSRMLS_CC);
mlumishb892a272014-12-09 16:28:23 -0800185 return;
186 }
thinkeroua3730b72016-07-20 16:59:54 +0800187 wrapped_grpc_server_credentials *creds =
thinkeroufe037cb2018-05-16 12:51:28 +0800188 PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server_credentials, creds_obj);
murgatroid998b87e842015-03-04 12:14:53 -0800189 RETURN_LONG(grpc_server_add_secure_http2_port(server->wrapped, addr,
190 creds->wrapped));
mlumishb892a272014-12-09 16:28:23 -0800191}
192
193/**
194 * Start a server - tells all listeners to start listening
thinkerou03dc2192016-08-16 19:31:44 +0800195 * @return void
mlumishb892a272014-12-09 16:28:23 -0800196 */
Craig Tillerb5dcec52015-01-13 11:13:42 -0800197PHP_METHOD(Server, start) {
thinkeroufe037cb2018-05-16 12:51:28 +0800198 wrapped_grpc_server *server =
199 PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
mlumishb892a272014-12-09 16:28:23 -0800200 grpc_server_start(server->wrapped);
201}
202
Stanley Cheung6a5c83d2017-02-16 12:25:32 -0800203ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 0)
204 ZEND_ARG_INFO(0, args)
205ZEND_END_ARG_INFO()
206
207ZEND_BEGIN_ARG_INFO_EX(arginfo_requestCall, 0, 0, 0)
208ZEND_END_ARG_INFO()
209
210ZEND_BEGIN_ARG_INFO_EX(arginfo_addHttp2Port, 0, 0, 1)
211 ZEND_ARG_INFO(0, addr)
212ZEND_END_ARG_INFO()
213
214ZEND_BEGIN_ARG_INFO_EX(arginfo_addSecureHttp2Port, 0, 0, 2)
215 ZEND_ARG_INFO(0, addr)
216 ZEND_ARG_INFO(0, server_creds)
217ZEND_END_ARG_INFO()
218
219ZEND_BEGIN_ARG_INFO_EX(arginfo_start, 0, 0, 0)
220ZEND_END_ARG_INFO()
221
mlumishb892a272014-12-09 16:28:23 -0800222static zend_function_entry server_methods[] = {
Stanley Cheung6a5c83d2017-02-16 12:25:32 -0800223 PHP_ME(Server, __construct, arginfo_construct,
224 ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
225 PHP_ME(Server, requestCall, arginfo_requestCall,
226 ZEND_ACC_PUBLIC)
227 PHP_ME(Server, addHttp2Port, arginfo_addHttp2Port,
228 ZEND_ACC_PUBLIC)
229 PHP_ME(Server, addSecureHttp2Port, arginfo_addSecureHttp2Port,
230 ZEND_ACC_PUBLIC)
231 PHP_ME(Server, start, arginfo_start,
232 ZEND_ACC_PUBLIC)
thinkerou5dafd822016-07-28 22:43:38 +0800233 PHP_FE_END
thinkeroua3730b72016-07-20 16:59:54 +0800234};
mlumishb892a272014-12-09 16:28:23 -0800235
Craig Tillerb5dcec52015-01-13 11:13:42 -0800236void grpc_init_server(TSRMLS_D) {
mlumishb892a272014-12-09 16:28:23 -0800237 zend_class_entry ce;
238 INIT_CLASS_ENTRY(ce, "Grpc\\Server", server_methods);
239 ce.create_object = create_wrapped_grpc_server;
240 grpc_ce_server = zend_register_internal_class(&ce TSRMLS_CC);
thinkerou5dafd822016-07-28 22:43:38 +0800241 PHP_GRPC_INIT_HANDLER(wrapped_grpc_server, server_ce_handlers);
mlumishb892a272014-12-09 16:28:23 -0800242}