Overview

Namespaces

  • Grpc

Classes

  • Grpc\AbstractCall
  • Grpc\BaseStub
  • Grpc\BidiStreamingCall
  • Grpc\ClientStreamingCall
  • Grpc\ServerStreamingCall
  • Grpc\UnaryCall
  • Overview
  • Namespace
  • Class
  1: <?php
  2: /*
  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:  */
 34: 
 35: namespace Grpc;
 36: 
 37: /**
 38:  * Base class for generated client stubs. Stub methods are expected to call
 39:  * _simpleRequest or _streamRequest and return the result.
 40:  */
 41: class BaseStub
 42: {
 43:     private $hostname;
 44:     private $hostname_override;
 45:     private $channel;
 46: 
 47:     // a callback function
 48:     private $update_metadata;
 49: 
 50:     /**
 51:      * @param string  $hostname
 52:      * @param array   $opts
 53:      *  - 'update_metadata': (optional) a callback function which takes in a
 54:      * metadata array, and returns an updated metadata array
 55:      *  - 'grpc.primary_user_agent': (optional) a user-agent string
 56:      * @param Channel $channel An already created Channel object (optional)
 57:      */
 58:     public function __construct($hostname, $opts, Channel $channel = null)
 59:     {
 60:         $ssl_roots = file_get_contents(
 61:             dirname(__FILE__).'/../../../../etc/roots.pem');
 62:         ChannelCredentials::setDefaultRootsPem($ssl_roots);
 63: 
 64:         $this->hostname = $hostname;
 65:         $this->update_metadata = null;
 66:         if (isset($opts['update_metadata'])) {
 67:             if (is_callable($opts['update_metadata'])) {
 68:                 $this->update_metadata = $opts['update_metadata'];
 69:             }
 70:             unset($opts['update_metadata']);
 71:         }
 72:         $package_config = json_decode(
 73:             file_get_contents(dirname(__FILE__).'/../../composer.json'), true);
 74:         if (!empty($opts['grpc.primary_user_agent'])) {
 75:             $opts['grpc.primary_user_agent'] .= ' ';
 76:         } else {
 77:             $opts['grpc.primary_user_agent'] = '';
 78:         }
 79:         if (!empty($opts['grpc.ssl_target_name_override'])) {
 80:             $this->hostname_override = $opts['grpc.ssl_target_name_override'];
 81:         }
 82:         $opts['grpc.primary_user_agent'] .=
 83:             'grpc-php/'.$package_config['version'];
 84:         if (!array_key_exists('credentials', $opts)) {
 85:             throw new \Exception("The opts['credentials'] key is now ".
 86:                                  'required. Please see one of the '.
 87:                                  'ChannelCredentials::create methods');
 88:         }
 89:         if ($channel) {
 90:             if (!is_a($channel, 'Channel')) {
 91:                 throw new \Exception('The channel argument is not a'.
 92:                                      'Channel object');
 93:             }
 94:             $this->channel = $channel;
 95:         } else {
 96:             $this->channel = new Channel($hostname, $opts);
 97:         }
 98:     }
 99: 
100:     /**
101:      * @return string The URI of the endpoint
102:      */
103:     public function getTarget()
104:     {
105:         return $this->channel->getTarget();
106:     }
107: 
108:     /**
109:      * @param bool $try_to_connect (optional)
110:      *
111:      * @return int The grpc connectivity state
112:      */
113:     public function getConnectivityState($try_to_connect = false)
114:     {
115:         return $this->channel->getConnectivityState($try_to_connect);
116:     }
117: 
118:     /**
119:      * @param int $timeout in microseconds
120:      *
121:      * @return bool true if channel is ready
122:      * @throw Exception if channel is in FATAL_ERROR state
123:      */
124:     public function waitForReady($timeout)
125:     {
126:         $new_state = $this->getConnectivityState(true);
127:         if ($this->_checkConnectivityState($new_state)) {
128:             return true;
129:         }
130: 
131:         $now = Timeval::now();
132:         $delta = new Timeval($timeout);
133:         $deadline = $now->add($delta);
134: 
135:         while ($this->channel->watchConnectivityState($new_state, $deadline)) {
136:             // state has changed before deadline
137:             $new_state = $this->getConnectivityState();
138:             if ($this->_checkConnectivityState($new_state)) {
139:                 return true;
140:             }
141:         }
142:         // deadline has passed
143:         $new_state = $this->getConnectivityState();
144: 
145:         return $this->_checkConnectivityState($new_state);
146:     }
147: 
148:     /**
149:      * Close the communication channel associated with this stub.
150:      */
151:     public function close()
152:     {
153:         $this->channel->close();
154:     }
155: 
156:     /**
157:      * @param $new_state Connect state
158:      *
159:      * @return bool true if state is CHANNEL_READY
160:      * @throw Exception if state is CHANNEL_FATAL_FAILURE
161:      */
162:     private function _checkConnectivityState($new_state)
163:     {
164:         if ($new_state == \Grpc\CHANNEL_READY) {
165:             return true;
166:         }
167:         if ($new_state == \Grpc\CHANNEL_FATAL_FAILURE) {
168:             throw new \Exception('Failed to connect to server');
169:         }
170: 
171:         return false;
172:     }
173: 
174:     /**
175:      * constructs the auth uri for the jwt.
176:      *
177:      * @param string $method The method string
178:      *
179:      * @return string The URL string
180:      */
181:     private function _get_jwt_aud_uri($method)
182:     {
183:         $last_slash_idx = strrpos($method, '/');
184:         if ($last_slash_idx === false) {
185:             throw new \InvalidArgumentException(
186:                 'service name must have a slash');
187:         }
188:         $service_name = substr($method, 0, $last_slash_idx);
189: 
190:         if ($this->hostname_override) {
191:             $hostname = $this->hostname_override;
192:         } else {
193:             $hostname = $this->hostname;
194:         }
195: 
196:         return 'https://'.$hostname.$service_name;
197:     }
198: 
199:     /**
200:      * validate and normalize the metadata array.
201:      *
202:      * @param array $metadata The metadata map
203:      *
204:      * @return array $metadata Validated and key-normalized metadata map
205:      * @throw InvalidArgumentException if key contains invalid characters
206:      */
207:     private function _validate_and_normalize_metadata($metadata)
208:     {
209:         $metadata_copy = [];
210:         foreach ($metadata as $key => $value) {
211:             if (!preg_match('/^[A-Za-z\d_-]+$/', $key)) {
212:                 throw new \InvalidArgumentException(
213:                     'Metadata keys must be nonempty strings containing only '.
214:                     'alphanumeric characters, hyphens and underscores');
215:             }
216:             $metadata_copy[strtolower($key)] = $value;
217:         }
218: 
219:         return $metadata_copy;
220:     }
221: 
222:     /* This class is intended to be subclassed by generated code, so
223:      * all functions begin with "_" to avoid name collisions. */
224: 
225:     /**
226:      * Call a remote method that takes a single argument and has a
227:      * single output.
228:      *
229:      * @param string   $method      The name of the method to call
230:      * @param mixed    $argument    The argument to the method
231:      * @param callable $deserialize A function that deserializes the response
232:      * @param array    $metadata    A metadata map to send to the server
233:      *                              (optional)
234:      * @param array    $options     An array of options (optional)
235:      *
236:      * @return SimpleSurfaceActiveCall The active call object
237:      */
238:     protected function _simpleRequest($method,
239:                                    $argument,
240:                                    $deserialize,
241:                                    array $metadata = [],
242:                                    array $options = [])
243:     {
244:         $call = new UnaryCall($this->channel,
245:                               $method,
246:                               $deserialize,
247:                               $options);
248:         $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
249:         if (is_callable($this->update_metadata)) {
250:             $metadata = call_user_func($this->update_metadata,
251:                                         $metadata,
252:                                         $jwt_aud_uri);
253:         }
254:         $metadata = $this->_validate_and_normalize_metadata(
255:             $metadata);
256:         $call->start($argument, $metadata, $options);
257: 
258:         return $call;
259:     }
260: 
261:     /**
262:      * Call a remote method that takes a stream of arguments and has a single
263:      * output.
264:      *
265:      * @param string   $method      The name of the method to call
266:      * @param callable $deserialize A function that deserializes the response
267:      * @param array    $metadata    A metadata map to send to the server
268:      *                              (optional)
269:      * @param array    $options     An array of options (optional)
270:      *
271:      * @return ClientStreamingSurfaceActiveCall The active call object
272:      */
273:     protected function _clientStreamRequest($method,
274:                                          $deserialize,
275:                                          array $metadata = [],
276:                                          array $options = [])
277:     {
278:         $call = new ClientStreamingCall($this->channel,
279:                                         $method,
280:                                         $deserialize,
281:                                         $options);
282:         $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
283:         if (is_callable($this->update_metadata)) {
284:             $metadata = call_user_func($this->update_metadata,
285:                                         $metadata,
286:                                         $jwt_aud_uri);
287:         }
288:         $metadata = $this->_validate_and_normalize_metadata(
289:             $metadata);
290:         $call->start($metadata);
291: 
292:         return $call;
293:     }
294: 
295:     /**
296:      * Call a remote method that takes a single argument and returns a stream
297:      * of responses.
298:      *
299:      * @param string   $method      The name of the method to call
300:      * @param mixed    $argument    The argument to the method
301:      * @param callable $deserialize A function that deserializes the responses
302:      * @param array    $metadata    A metadata map to send to the server
303:      *                              (optional)
304:      * @param array    $options     An array of options (optional)
305:      *
306:      * @return ServerStreamingSurfaceActiveCall The active call object
307:      */
308:     protected function _serverStreamRequest($method,
309:                                          $argument,
310:                                          $deserialize,
311:                                          array $metadata = [],
312:                                          array $options = [])
313:     {
314:         $call = new ServerStreamingCall($this->channel,
315:                                         $method,
316:                                         $deserialize,
317:                                         $options);
318:         $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
319:         if (is_callable($this->update_metadata)) {
320:             $metadata = call_user_func($this->update_metadata,
321:                                         $metadata,
322:                                         $jwt_aud_uri);
323:         }
324:         $metadata = $this->_validate_and_normalize_metadata(
325:             $metadata);
326:         $call->start($argument, $metadata, $options);
327: 
328:         return $call;
329:     }
330: 
331:     /**
332:      * Call a remote method with messages streaming in both directions.
333:      *
334:      * @param string   $method      The name of the method to call
335:      * @param callable $deserialize A function that deserializes the responses
336:      * @param array    $metadata    A metadata map to send to the server
337:      *                              (optional)
338:      * @param array    $options     An array of options (optional)
339:      *
340:      * @return BidiStreamingSurfaceActiveCall The active call object
341:      */
342:     protected function _bidiRequest($method,
343:                                  $deserialize,
344:                                  array $metadata = [],
345:                                  array $options = [])
346:     {
347:         $call = new BidiStreamingCall($this->channel,
348:                                       $method,
349:                                       $deserialize,
350:                                       $options);
351:         $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
352:         if (is_callable($this->update_metadata)) {
353:             $metadata = call_user_func($this->update_metadata,
354:                                         $metadata,
355:                                         $jwt_aud_uri);
356:         }
357:         $metadata = $this->_validate_and_normalize_metadata(
358:             $metadata);
359:         $call->start($metadata);
360: 
361:         return $call;
362:     }
363: }
364: 
API documentation generated by ApiGen