@@ -41,6 +41,26 @@ use proto::Body;
41
41
pub use proto:: response:: Response ;
42
42
pub use proto:: request:: Request ;
43
43
44
+ // The `Server` can be created use its own `Core`, or an shared `Handle`.
45
+ enum Reactor {
46
+ // Own its `Core`
47
+ Core ( Core ) ,
48
+ // Share `Handle` with others
49
+ Handle ( Handle ) ,
50
+ }
51
+
52
+ impl Reactor {
53
+ /// Returns a handle to the underlying event loop that this server will be
54
+ /// running on.
55
+ #[ inline]
56
+ pub fn handle ( & self ) -> Handle {
57
+ match * self {
58
+ Reactor :: Core ( ref core) => core. handle ( ) ,
59
+ Reactor :: Handle ( ref handle) => handle. clone ( ) ,
60
+ }
61
+ }
62
+ }
63
+
44
64
/// An instance of the HTTP protocol, and implementation of tokio-proto's
45
65
/// `ServerProto` trait.
46
66
///
@@ -63,7 +83,7 @@ where B: Stream<Error=::Error>,
63
83
{
64
84
protocol : Http < B :: Item > ,
65
85
new_service : S ,
66
- core : Core ,
86
+ reactor : Reactor ,
67
87
listener : TcpListener ,
68
88
shutdown_timeout : Duration ,
69
89
}
@@ -117,10 +137,34 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
117
137
118
138
Ok ( Server {
119
139
new_service : new_service,
120
- core : core,
140
+ reactor : Reactor :: Core ( core) ,
141
+ listener : listener,
142
+ protocol : self . clone ( ) ,
143
+ shutdown_timeout : Duration :: new ( 1 , 0 ) ,
144
+ } )
145
+ }
146
+
147
+ /// This method allows the ability to share a `Core` with multiple servers.
148
+ ///
149
+ /// Bind the provided `addr` and return a server with a shared `Core`.
150
+ ///
151
+ /// This is method will bind the `addr` provided with a new TCP listener ready
152
+ /// to accept connections. Each connection will be processed with the
153
+ /// `new_service` object provided as well, creating a new service per
154
+ /// connection.
155
+ pub fn bind_handle < S , Bd > ( & self , addr : & SocketAddr , new_service : S , handle : & Handle ) -> :: Result < Server < S , Bd > >
156
+ where S : NewService < Request = Request , Response = Response < Bd > , Error = :: Error > + ' static ,
157
+ Bd : Stream < Item =B , Error =:: Error > ,
158
+ {
159
+ let listener = TcpListener :: bind ( addr, & handle) ?;
160
+
161
+ Ok ( Server {
162
+ new_service : new_service,
163
+ reactor : Reactor :: Handle ( handle. clone ( ) ) ,
121
164
listener : listener,
122
165
protocol : self . clone ( ) ,
123
166
shutdown_timeout : Duration :: new ( 1 , 0 ) ,
167
+
124
168
} )
125
169
}
126
170
@@ -404,7 +448,7 @@ impl<S, B> Server<S, B>
404
448
/// Returns a handle to the underlying event loop that this server will be
405
449
/// running on.
406
450
pub fn handle ( & self ) -> Handle {
407
- self . core . handle ( )
451
+ self . reactor . handle ( )
408
452
}
409
453
410
454
/// Configure the amount of time this server will wait for a "graceful
@@ -444,7 +488,13 @@ impl<S, B> Server<S, B>
444
488
pub fn run_until < F > ( self , shutdown_signal : F ) -> :: Result < ( ) >
445
489
where F : Future < Item = ( ) , Error = ( ) > ,
446
490
{
447
- let Server { protocol, new_service, mut core, listener, shutdown_timeout } = self ;
491
+ let Server { protocol, new_service, reactor, listener, shutdown_timeout } = self ;
492
+
493
+ let mut core = match reactor {
494
+ Reactor :: Core ( core) => core,
495
+ _ => panic ! ( "Server does not own its core, use `Handle::spawn()` to run the service!" ) ,
496
+ } ;
497
+
448
498
let handle = core. handle ( ) ;
449
499
450
500
// Mini future to track the number of active services
@@ -496,6 +546,38 @@ impl<S, B> Server<S, B>
496
546
}
497
547
}
498
548
549
+ impl < S , B > Future for Server < S , B >
550
+ where S : NewService < Request = Request , Response = Response < B > , Error = :: Error > + ' static ,
551
+ B : Stream < Error =:: Error > + ' static ,
552
+ B :: Item : AsRef < [ u8 ] > ,
553
+ {
554
+ type Item = ( ) ;
555
+ type Error = ( ) ;
556
+
557
+ fn poll ( & mut self ) -> Poll < Self :: Item , Self :: Error > {
558
+ if let Reactor :: Core ( _) = self . reactor {
559
+ panic ! ( "Server owns its core, use `Server::run()` to run the service!" )
560
+ }
561
+
562
+ loop {
563
+ match self . listener . accept ( ) {
564
+ Ok ( ( socket, addr) ) => {
565
+ // TODO: use the NotifyService
566
+ match self . new_service . new_service ( ) {
567
+ Ok ( srv) => self . protocol . bind_connection ( & self . handle ( ) ,
568
+ socket,
569
+ addr,
570
+ srv) ,
571
+ Err ( e) => debug ! ( "internal error: {:?}" , e) ,
572
+ }
573
+ }
574
+ Err ( ref e) if e. kind ( ) == io:: ErrorKind :: WouldBlock => return Ok ( Async :: NotReady ) ,
575
+ Err ( e) => debug ! ( "internal error: {:?}" , e) ,
576
+ }
577
+ }
578
+ }
579
+ }
580
+
499
581
impl < S : fmt:: Debug , B : Stream < Error =:: Error > > fmt:: Debug for Server < S , B >
500
582
where B :: Item : AsRef < [ u8 ] >
501
583
{
0 commit comments