1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 //   http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17 
18 //! Types used to implement a Thrift server.
19 
20 use crate::protocol::{TInputProtocol, TMessageIdentifier, TMessageType, TOutputProtocol};
21 use crate::{ApplicationError, ApplicationErrorKind};
22 
23 mod multiplexed;
24 mod threaded;
25 
26 pub use self::multiplexed::TMultiplexedProcessor;
27 pub use self::threaded::TServer;
28 
29 /// Handles incoming Thrift messages and dispatches them to the user-defined
30 /// handler functions.
31 ///
32 /// An implementation is auto-generated for each Thrift service. When used by a
33 /// server (for example, a `TSimpleServer`), it will demux incoming service
34 /// calls and invoke the corresponding user-defined handler function.
35 ///
36 /// # Examples
37 ///
38 /// Create and start a server using the auto-generated `TProcessor` for
39 /// a Thrift service `SimpleService`.
40 ///
41 /// ```no_run
42 /// use thrift::protocol::{TInputProtocol, TOutputProtocol};
43 /// use thrift::server::TProcessor;
44 ///
45 /// //
46 /// // auto-generated
47 /// //
48 ///
49 /// // processor for `SimpleService`
50 /// struct SimpleServiceSyncProcessor;
51 /// impl SimpleServiceSyncProcessor {
52 ///     fn new<H: SimpleServiceSyncHandler>(processor: H) -> SimpleServiceSyncProcessor {
53 ///         unimplemented!();
54 ///     }
55 /// }
56 ///
57 /// // `TProcessor` implementation for `SimpleService`
58 /// impl TProcessor for SimpleServiceSyncProcessor {
59 ///     fn process(&self, i: &mut dyn TInputProtocol, o: &mut dyn TOutputProtocol) -> thrift::Result<()> {
60 ///         unimplemented!();
61 ///     }
62 /// }
63 ///
64 /// // service functions for SimpleService
65 /// trait SimpleServiceSyncHandler {
66 ///     fn service_call(&self) -> thrift::Result<()>;
67 /// }
68 ///
69 /// //
70 /// // user-code follows
71 /// //
72 ///
73 /// // define a handler that will be invoked when `service_call` is received
74 /// struct SimpleServiceHandlerImpl;
75 /// impl SimpleServiceSyncHandler for SimpleServiceHandlerImpl {
76 ///     fn service_call(&self) -> thrift::Result<()> {
77 ///         unimplemented!();
78 ///     }
79 /// }
80 ///
81 /// // instantiate the processor
82 /// let processor = SimpleServiceSyncProcessor::new(SimpleServiceHandlerImpl {});
83 ///
84 /// // at this point you can pass the processor to the server
85 /// // let server = TServer::new(..., processor);
86 /// ```
87 pub trait TProcessor {
88     /// Process a Thrift service call.
89     ///
90     /// Reads arguments from `i`, executes the user's handler code, and writes
91     /// the response to `o`.
92     ///
93     /// Returns `()` if the handler was executed; `Err` otherwise.
process(&self, i: &mut dyn TInputProtocol, o: &mut dyn TOutputProtocol) -> crate::Result<()>94     fn process(&self, i: &mut dyn TInputProtocol, o: &mut dyn TOutputProtocol) -> crate::Result<()>;
95 }
96 
97 /// Convenience function used in generated `TProcessor` implementations to
98 /// return an `ApplicationError` if thrift message processing failed.
handle_process_result( msg_ident: &TMessageIdentifier, res: crate::Result<()>, o_prot: &mut dyn TOutputProtocol, ) -> crate::Result<()>99 pub fn handle_process_result(
100     msg_ident: &TMessageIdentifier,
101     res: crate::Result<()>,
102     o_prot: &mut dyn TOutputProtocol,
103 ) -> crate::Result<()> {
104     if let Err(e) = res {
105         let e = match e {
106             crate::Error::Application(a) => a,
107             _ => ApplicationError::new(ApplicationErrorKind::Unknown, format!("{:?}", e)),
108         };
109 
110         let ident = TMessageIdentifier::new(
111             msg_ident.name.clone(),
112             TMessageType::Exception,
113             msg_ident.sequence_number,
114         );
115 
116         o_prot.write_message_begin(&ident)?;
117         crate::Error::write_application_error_to_out_protocol(&e, o_prot)?;
118         o_prot.write_message_end()?;
119         o_prot.flush()
120     } else {
121         Ok(())
122     }
123 }
124