1# Protocol Buffers - Google's data interchange format
2# Copyright 2008 Google Inc.  All rights reserved.
3# http://code.google.com/p/protobuf/
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9#     * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11#     * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15#     * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31"""DEPRECATED:  Declares the RPC service interfaces.
32
33This module declares the abstract interfaces underlying proto2 RPC
34services.  These are intended to be independent of any particular RPC
35implementation, so that proto2 services can be used on top of a variety
36of implementations.  Starting with version 2.3.0, RPC implementations should
37not try to build on these, but should instead provide code generator plugins
38which generate code specific to the particular RPC implementation.  This way
39the generated code can be more appropriate for the implementation in use
40and can avoid unnecessary layers of indirection.
41"""
42
43__author__ = 'petar@google.com (Petar Petrov)'
44
45
46class RpcException(Exception):
47  """Exception raised on failed blocking RPC method call."""
48  pass
49
50
51class Service(object):
52
53  """Abstract base interface for protocol-buffer-based RPC services.
54
55  Services themselves are abstract classes (implemented either by servers or as
56  stubs), but they subclass this base interface. The methods of this
57  interface can be used to call the methods of the service without knowing
58  its exact type at compile time (analogous to the Message interface).
59  """
60
61  def GetDescriptor():
62    """Retrieves this service's descriptor."""
63    raise NotImplementedError
64
65  def CallMethod(self, method_descriptor, rpc_controller,
66                 request, done):
67    """Calls a method of the service specified by method_descriptor.
68
69    If "done" is None then the call is blocking and the response
70    message will be returned directly.  Otherwise the call is asynchronous
71    and "done" will later be called with the response value.
72
73    In the blocking case, RpcException will be raised on error.
74
75    Preconditions:
76    * method_descriptor.service == GetDescriptor
77    * request is of the exact same classes as returned by
78      GetRequestClass(method).
79    * After the call has started, the request must not be modified.
80    * "rpc_controller" is of the correct type for the RPC implementation being
81      used by this Service.  For stubs, the "correct type" depends on the
82      RpcChannel which the stub is using.
83
84    Postconditions:
85    * "done" will be called when the method is complete.  This may be
86      before CallMethod() returns or it may be at some point in the future.
87    * If the RPC failed, the response value passed to "done" will be None.
88      Further details about the failure can be found by querying the
89      RpcController.
90    """
91    raise NotImplementedError
92
93  def GetRequestClass(self, method_descriptor):
94    """Returns the class of the request message for the specified method.
95
96    CallMethod() requires that the request is of a particular subclass of
97    Message. GetRequestClass() gets the default instance of this required
98    type.
99
100    Example:
101      method = service.GetDescriptor().FindMethodByName("Foo")
102      request = stub.GetRequestClass(method)()
103      request.ParseFromString(input)
104      service.CallMethod(method, request, callback)
105    """
106    raise NotImplementedError
107
108  def GetResponseClass(self, method_descriptor):
109    """Returns the class of the response message for the specified method.
110
111    This method isn't really needed, as the RpcChannel's CallMethod constructs
112    the response protocol message. It's provided anyway in case it is useful
113    for the caller to know the response type in advance.
114    """
115    raise NotImplementedError
116
117
118class RpcController(object):
119
120  """An RpcController mediates a single method call.
121
122  The primary purpose of the controller is to provide a way to manipulate
123  settings specific to the RPC implementation and to find out about RPC-level
124  errors. The methods provided by the RpcController interface are intended
125  to be a "least common denominator" set of features which we expect all
126  implementations to support.  Specific implementations may provide more
127  advanced features (e.g. deadline propagation).
128  """
129
130  # Client-side methods below
131
132  def Reset(self):
133    """Resets the RpcController to its initial state.
134
135    After the RpcController has been reset, it may be reused in
136    a new call. Must not be called while an RPC is in progress.
137    """
138    raise NotImplementedError
139
140  def Failed(self):
141    """Returns true if the call failed.
142
143    After a call has finished, returns true if the call failed.  The possible
144    reasons for failure depend on the RPC implementation.  Failed() must not
145    be called before a call has finished.  If Failed() returns true, the
146    contents of the response message are undefined.
147    """
148    raise NotImplementedError
149
150  def ErrorText(self):
151    """If Failed is true, returns a human-readable description of the error."""
152    raise NotImplementedError
153
154  def StartCancel(self):
155    """Initiate cancellation.
156
157    Advises the RPC system that the caller desires that the RPC call be
158    canceled.  The RPC system may cancel it immediately, may wait awhile and
159    then cancel it, or may not even cancel the call at all.  If the call is
160    canceled, the "done" callback will still be called and the RpcController
161    will indicate that the call failed at that time.
162    """
163    raise NotImplementedError
164
165  # Server-side methods below
166
167  def SetFailed(self, reason):
168    """Sets a failure reason.
169
170    Causes Failed() to return true on the client side.  "reason" will be
171    incorporated into the message returned by ErrorText().  If you find
172    you need to return machine-readable information about failures, you
173    should incorporate it into your response protocol buffer and should
174    NOT call SetFailed().
175    """
176    raise NotImplementedError
177
178  def IsCanceled(self):
179    """Checks if the client cancelled the RPC.
180
181    If true, indicates that the client canceled the RPC, so the server may
182    as well give up on replying to it.  The server should still call the
183    final "done" callback.
184    """
185    raise NotImplementedError
186
187  def NotifyOnCancel(self, callback):
188    """Sets a callback to invoke on cancel.
189
190    Asks that the given callback be called when the RPC is canceled.  The
191    callback will always be called exactly once.  If the RPC completes without
192    being canceled, the callback will be called after completion.  If the RPC
193    has already been canceled when NotifyOnCancel() is called, the callback
194    will be called immediately.
195
196    NotifyOnCancel() must be called no more than once per request.
197    """
198    raise NotImplementedError
199
200
201class RpcChannel(object):
202
203  """Abstract interface for an RPC channel.
204
205  An RpcChannel represents a communication line to a service which can be used
206  to call that service's methods.  The service may be running on another
207  machine. Normally, you should not use an RpcChannel directly, but instead
208  construct a stub {@link Service} wrapping it.  Example:
209
210  Example:
211    RpcChannel channel = rpcImpl.Channel("remotehost.example.com:1234")
212    RpcController controller = rpcImpl.Controller()
213    MyService service = MyService_Stub(channel)
214    service.MyMethod(controller, request, callback)
215  """
216
217  def CallMethod(self, method_descriptor, rpc_controller,
218                 request, response_class, done):
219    """Calls the method identified by the descriptor.
220
221    Call the given method of the remote service.  The signature of this
222    procedure looks the same as Service.CallMethod(), but the requirements
223    are less strict in one important way:  the request object doesn't have to
224    be of any specific class as long as its descriptor is method.input_type.
225    """
226    raise NotImplementedError
227