blob: c26be607ffc98bb618fbdfac6e2b9e7cfd2a39c4 [file] [log] [blame]
mlumishb892a272014-12-09 16:28:23 -08001<?php
Craig Tiller2e498aa2015-02-16 12:09:31 -08002/*
3 *
4 * Copyright 2015, Google Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following disclaimer
15 * in the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Google Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
Stanley Cheungd5b20562015-10-27 13:27:05 -070034
mlumishb892a272014-12-09 16:28:23 -080035namespace Grpc;
mlumishb892a272014-12-09 16:28:23 -080036
37/**
38 * Base class for generated client stubs. Stub methods are expected to call
39 * _simpleRequest or _streamRequest and return the result.
40 */
Stanley Cheungd5b20562015-10-27 13:27:05 -070041class BaseStub
42{
43 private $hostname;
44 private $channel;
mlumishb892a272014-12-09 16:28:23 -080045
Stanley Cheungd5b20562015-10-27 13:27:05 -070046 // a callback function
47 private $update_metadata;
mlumishb892a272014-12-09 16:28:23 -080048
Stanley Cheungd5b20562015-10-27 13:27:05 -070049 /**
50 * @param $hostname string
51 * @param $opts array
52 * - 'update_metadata': (optional) a callback function which takes in a
53 * metadata array, and returns an updated metadata array
54 */
55 public function __construct($hostname, $opts)
56 {
57 $this->hostname = $hostname;
58 $this->update_metadata = null;
59 if (isset($opts['update_metadata'])) {
60 if (is_callable($opts['update_metadata'])) {
61 $this->update_metadata = $opts['update_metadata'];
62 }
63 unset($opts['update_metadata']);
64 }
65 $package_config = json_decode(
66 file_get_contents(dirname(__FILE__).'/../../composer.json'), true);
67 $opts['grpc.primary_user_agent'] =
68 'grpc-php/'.$package_config['version'];
69 $this->channel = new Channel($hostname, $opts);
Stanley Cheung04b7a412015-08-13 09:39:04 -070070 }
71
Stanley Cheungd5b20562015-10-27 13:27:05 -070072 /**
73 * @return string The URI of the endpoint.
74 */
75 public function getTarget()
76 {
77 return $this->channel->getTarget();
Stanley Cheung04b7a412015-08-13 09:39:04 -070078 }
Stanley Cheung04b7a412015-08-13 09:39:04 -070079
Stanley Cheungd5b20562015-10-27 13:27:05 -070080 /**
81 * @param $try_to_connect bool
82 *
83 * @return int The grpc connectivity state
84 */
85 public function getConnectivityState($try_to_connect = false)
86 {
87 return $this->channel->getConnectivityState($try_to_connect);
Stanley Cheung04b7a412015-08-13 09:39:04 -070088 }
Stanley Cheungd5b20562015-10-27 13:27:05 -070089
90 /**
91 * @param $timeout in microseconds
92 *
93 * @return bool true if channel is ready
94 * @throw Exception if channel is in FATAL_ERROR state
95 */
96 public function waitForReady($timeout)
97 {
98 $new_state = $this->getConnectivityState(true);
99 if ($this->_checkConnectivityState($new_state)) {
100 return true;
101 }
102
103 $now = Timeval::now();
104 $delta = new Timeval($timeout);
105 $deadline = $now->add($delta);
106
107 while ($this->channel->watchConnectivityState($new_state, $deadline)) {
108 // state has changed before deadline
109 $new_state = $this->getConnectivityState();
110 if ($this->_checkConnectivityState($new_state)) {
111 return true;
112 }
113 }
114 // deadline has passed
115 $new_state = $this->getConnectivityState();
116
117 return $this->_checkConnectivityState($new_state);
Stanley Cheung04b7a412015-08-13 09:39:04 -0700118 }
Stanley Cheung04b7a412015-08-13 09:39:04 -0700119
Stanley Cheungd5b20562015-10-27 13:27:05 -0700120 private function _checkConnectivityState($new_state)
121 {
122 if ($new_state == \Grpc\CHANNEL_READY) {
123 return true;
124 }
125 if ($new_state == \Grpc\CHANNEL_FATAL_FAILURE) {
126 throw new \Exception('Failed to connect to server');
127 }
mlumishb892a272014-12-09 16:28:23 -0800128
Stanley Cheungd5b20562015-10-27 13:27:05 -0700129 return false;
Stanley Cheungf4206872015-05-12 17:39:30 -0700130 }
Stanley Cheungf4206872015-05-12 17:39:30 -0700131
Stanley Cheungd5b20562015-10-27 13:27:05 -0700132 /**
133 * Close the communication channel associated with this stub.
134 */
135 public function close()
136 {
137 $this->channel->close();
Stanley Cheungcc019af2015-06-15 11:45:00 -0700138 }
Stanley Cheungcc019af2015-06-15 11:45:00 -0700139
Stanley Cheungd5b20562015-10-27 13:27:05 -0700140 /**
141 * constructs the auth uri for the jwt.
142 */
143 private function _get_jwt_aud_uri($method)
144 {
145 $last_slash_idx = strrpos($method, '/');
146 if ($last_slash_idx === false) {
147 throw new \InvalidArgumentException(
148 'service name must have a slash');
149 }
150 $service_name = substr($method, 0, $last_slash_idx);
151
152 return 'https://'.$this->hostname.$service_name;
Stanley Cheungb0cd08a2015-10-09 16:58:01 -0700153 }
Stanley Cheungb0cd08a2015-10-09 16:58:01 -0700154
Stanley Cheungd5b20562015-10-27 13:27:05 -0700155 /**
156 * extract $timeout from $metadata.
157 *
158 * @param $metadata The metadata map
159 *
160 * @return list($metadata_copy, $timeout)
161 */
162 private function _extract_timeout_from_metadata($metadata)
163 {
164 $timeout = false;
165 $metadata_copy = $metadata;
166 if (isset($metadata['timeout'])) {
167 $timeout = $metadata['timeout'];
168 unset($metadata_copy['timeout']);
169 }
mlumishb892a272014-12-09 16:28:23 -0800170
Stanley Cheungd5b20562015-10-27 13:27:05 -0700171 return [$metadata_copy, $timeout];
172 }
173
174 /**
175 * validate and normalize the metadata array.
176 *
177 * @param $metadata The metadata map
178 *
179 * @return $metadata Validated and key-normalized metadata map
180 * @throw InvalidArgumentException if key contains invalid characters
181 */
182 private function _validate_and_normalize_metadata($metadata)
183 {
184 $metadata_copy = [];
185 foreach ($metadata as $key => $value) {
186 if (!preg_match('/^[A-Za-z\d_-]+$/', $key)) {
187 throw new \InvalidArgumentException(
188 'Metadata keys must be nonempty strings containing only '.
189 'alphanumeric characters, hyphens and underscores');
190 }
191 $metadata_copy[strtolower($key)] = $value;
192 }
193
194 return $metadata_copy;
195 }
196
197 /* This class is intended to be subclassed by generated code, so
198 * all functions begin with "_" to avoid name collisions. */
199
200 /**
201 * Call a remote method that takes a single argument and has a
202 * single output.
203 *
204 * @param string $method The name of the method to call
205 * @param $argument The argument to the method
206 * @param callable $deserialize A function that deserializes the response
207 * @param array $metadata A metadata map to send to the server
208 *
209 * @return SimpleSurfaceActiveCall The active call object
210 */
211 public function _simpleRequest($method,
212 $argument,
213 callable $deserialize,
214 $metadata = [],
215 $options = [])
216 {
217 list($actual_metadata, $timeout) =
218 $this->_extract_timeout_from_metadata($metadata);
219 $call = new UnaryCall($this->channel,
220 $method,
221 $deserialize,
222 $timeout);
223 $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
224 if (is_callable($this->update_metadata)) {
225 $actual_metadata = call_user_func($this->update_metadata,
226 $actual_metadata,
227 $jwt_aud_uri);
228 }
229 $actual_metadata = $this->_validate_and_normalize_metadata(
230 $actual_metadata);
231 $call->start($argument, $actual_metadata, $options);
232
233 return $call;
234 }
235
236 /**
237 * Call a remote method that takes a stream of arguments and has a single
238 * output.
239 *
240 * @param string $method The name of the method to call
241 * @param $arguments An array or Traversable of arguments to stream to the
242 * server
243 * @param callable $deserialize A function that deserializes the response
244 * @param array $metadata A metadata map to send to the server
245 *
246 * @return ClientStreamingSurfaceActiveCall The active call object
247 */
248 public function _clientStreamRequest($method,
249 callable $deserialize,
250 $metadata = [])
251 {
252 list($actual_metadata, $timeout) =
253 $this->_extract_timeout_from_metadata($metadata);
254 $call = new ClientStreamingCall($this->channel,
255 $method,
256 $deserialize,
257 $timeout);
258 $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
259 if (is_callable($this->update_metadata)) {
260 $actual_metadata = call_user_func($this->update_metadata,
261 $actual_metadata,
262 $jwt_aud_uri);
263 }
264 $actual_metadata = $this->_validate_and_normalize_metadata(
265 $actual_metadata);
266 $call->start($actual_metadata);
267
268 return $call;
269 }
270
271 /**
272 * Call a remote method that takes a single argument and returns a stream of
273 * responses.
274 *
275 * @param string $method The name of the method to call
276 * @param $argument The argument to the method
277 * @param callable $deserialize A function that deserializes the responses
278 * @param array $metadata A metadata map to send to the server
279 *
280 * @return ServerStreamingSurfaceActiveCall The active call object
281 */
282 public function _serverStreamRequest($method,
283 $argument,
284 callable $deserialize,
285 $metadata = [],
286 $options = [])
287 {
288 list($actual_metadata, $timeout) =
289 $this->_extract_timeout_from_metadata($metadata);
290 $call = new ServerStreamingCall($this->channel,
291 $method,
292 $deserialize,
293 $timeout);
294 $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
295 if (is_callable($this->update_metadata)) {
296 $actual_metadata = call_user_func($this->update_metadata,
297 $actual_metadata,
298 $jwt_aud_uri);
299 }
300 $actual_metadata = $this->_validate_and_normalize_metadata(
301 $actual_metadata);
302 $call->start($argument, $actual_metadata, $options);
303
304 return $call;
305 }
306
307 /**
308 * Call a remote method with messages streaming in both directions.
309 *
310 * @param string $method The name of the method to call
311 * @param callable $deserialize A function that deserializes the responses
312 * @param array $metadata A metadata map to send to the server
313 *
314 * @return BidiStreamingSurfaceActiveCall The active call object
315 */
316 public function _bidiRequest($method,
murgatroid9914d2ce22015-01-30 15:36:23 -0800317 callable $deserialize,
Stanley Cheungd5b20562015-10-27 13:27:05 -0700318 $metadata = [])
319 {
320 list($actual_metadata, $timeout) =
321 $this->_extract_timeout_from_metadata($metadata);
322 $call = new BidiStreamingCall($this->channel,
323 $method,
324 $deserialize,
325 $timeout);
326 $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
327 if (is_callable($this->update_metadata)) {
328 $actual_metadata = call_user_func($this->update_metadata,
Stanley Cheungf4206872015-05-12 17:39:30 -0700329 $actual_metadata,
330 $jwt_aud_uri);
Stanley Cheungd5b20562015-10-27 13:27:05 -0700331 }
332 $actual_metadata = $this->_validate_and_normalize_metadata(
333 $actual_metadata);
334 $call->start($actual_metadata);
mlumishb892a272014-12-09 16:28:23 -0800335
Stanley Cheungd5b20562015-10-27 13:27:05 -0700336 return $call;
Stanley Cheung2c9c7632015-04-20 14:13:54 -0700337 }
mlumishb892a272014-12-09 16:28:23 -0800338}