1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//! RPC framework in Rust
//!
//! copra is an [RPC] framework aimed at ease of use and configuration.
//! It can generate most of the boilerplate code in server and client side.
//! You only need to implement the core logic of services.
//!
//! [RPC]: https://en.wikipedia.org/wiki/Remote_procedure_call
//!
//! # Installation
//!
//! ## Protocol compiler installation
//!
//! `copra` uses [Protocol Buffers][protobuf] (a.k.a. protobuf) to exchange messages
//! and describe service signatures. The message and service descriptions are written
//! in `.proto` files, and `copra` depends on the protocol compiler to generate rust
//! code from these files.
//!
//! Visit [this website] and download
//! `proto-3.*.*-your-arch.zip` (`copra` needs protocol version 3), extract the
//! `protoc` executable to a folder you like, then add `protoc` to your `PATH`.
//!
//! [protobuf]: https://developers.google.com/protocol-buffers/
//! [this website]: https://github.com/google/protobuf/releases
//!
//! ## Cargo setup
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! copra = "0.1"
//! futures = "0.1"
//! tokio-core = "0.1"
//!
//! [build-dependencies]
//! protoc-rust-copra = "0.1"
//! ```
//!
//! # Examples
//!
//! Here is an example of implementing an echo RPC. First, create a file named
//! `echo.proto` and put it in the manifest directory (i.e. next to `Cargo.toml`).
//! Populate it with:
//!
//! ```protobuf
//! syntax = "proto3"
//!
//! message EchoMessage {
//!     string msg = 1;
//! }
//!
//! // Our echo service contains two method. One is sending back the original string
//! // directly, and the other is returning the string in reversed form.
//! service Echo {
//!     rpc echo(EchoMessage) returns (EchoMessage);
//!     rpc reverse_echo(EchoMessage) returns (EchoMessage);
//! }
//! ```
//!
//! Next, create a [`build.rs`][build-scripts] in the manifest directory, and add this to
//! it:
//!
//! ```no_run
//! extern crate protoc_rust_copra;
//!
//! fn main() {
//!     protoc_rust_copra::run(protoc_rust_copra::Args {
//!         out_dir: "src/protos",
//!         input: &["echo.proto"],
//!         includes: &[],
//!         rust_protobuf: true
//!     }).expect("Failed to compile proto files");
//! }
//! ```
//!
//! This will generate file `echo.rs` and `echo_copra.rs` in `src/protos`.
//!
//! Then, add this to `main.rs`:
//!
//! ```no_run
//! extern crate copra;
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use copra::{ChannelBuilder, Controller, MethodError, ServerBuilder, ServiceRegistry};
//! use futures::future::{self, Future, FutureResult};
//! use std::thread;
//! use tokio_core::reactor::Core;
//!
//! use protos::echo::EchoMessage;
//! use protos::echo_copra::{EchoRegistrant, EchoService, EchoStub};
//!
//! mod protos;
//!
//! // Service provider must implement Clone
//! #[derive(Clone)]
//! struct Echo;
//!
//! // EchoService is a trait for defining service logic
//! // It is generated by protoc-rust-copra
//! impl EchoService for Echo {
//!     type EchoFuture = FutureResult<(EchoMessage, Controller), MethodError>;
//!
//!     type ReverseEchoFuture = FutureResult<(EchoMessage, Controller), MethodError>;
//!
//!     fn echo(&self, (req, ctrl): (EchoMessage, Controller)) -> Self::EchoFuture {
//!         let mut response = EchoMessage::new();
//!         response.set_msg(req.msg);
//!         future::ok((response, ctrl))
//!     }
//!
//!     fn reverse_echo(
//!         &self,
//!         (req, ctrl): (EchoMessage, Controller)
//!     ) -> Self::ReverseEchoFuture {
//!         let rev: String = req.msg.chars().rev().collect();
//!         let mut response = EchoMessage::new();
//!         response.set_msg(rev);
//!         future::ok((response, ctrl))
//!     }
//! }
//!
//! fn main() {
//!     let addr = "127.0.0.1:8989";
//!
//!     // server side
//!     thread::spawn(move || {
//!         // register the service provider, so that it can be accessed
//!         let registrant = EchoRegistrant::new(Echo);
//!         let mut registry = ServiceRegistry::new();
//!         registry.register_service(registrant);
//!
//!         let server = ServerBuilder::new(addr, registry).build().unwrap();
//!         server.start();
//!     });
//!
//!     // client side
//!     let mut core = Core::new().unwrap();
//!     let handle = core.handle();
//!     let channel = core.run(ChannelBuilder::single_server(addr, handle).build())
//!         .unwrap();
//!     let stub = EchoStub::new(&channel);
//!
//!     let mut request = EchoMessage::new();
//!     request.set_msg("Hello world".to_string());
//!
//!     let (response, _info) = core.run(stub.echo(request.clone())).unwrap();
//!     println!("{}", response.msg);
//!
//!     let (response, _info) = core.run(stub.reverse_echo(request)).unwrap();
//!     println!("{}", response.msg);
//! }
//! ```
//!
//! Finally, build and run this example by executing:
//!
//! ```bash
//! $ cargo build
//! $ cargo run
//! ```
//!
//! [build-scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
//! 
//! # Note
//! 
//! This project is still in the early development stage. It basically works, but 
//! you should use it with caution.

#![warn(missing_docs, missing_debug_implementations)]

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate httparse;
#[macro_use]
extern crate log;
extern crate protobuf;
extern crate smallvec;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_proto;
extern crate tokio_service;
extern crate tokio_timer;
extern crate url;

#[cfg(test)]
extern crate rand;

pub use channel::ChannelBuilder;
pub use controller::Controller;
pub use dispatcher::ServiceRegistry;
pub use server::ServerBuilder;
pub use service::MethodError;

pub mod channel;
pub mod controller;
pub mod codec;
pub mod dispatcher;
pub mod load_balancer;
pub mod message;
pub mod protocol;
pub mod service;
pub mod stub;
pub mod server;
pub mod monitor;