6
6
7
7
//! Manages the connection between the API and your host.
8
8
9
+ use bytes:: { BufMut , BytesMut } ;
9
10
use errors:: * ;
11
+ use futures:: Future ;
12
+ use RemoteProvider ;
13
+ use serde:: Deserialize ;
14
+ use serde_json;
15
+ use std:: { io, result} ;
16
+ use std:: net:: SocketAddr ;
10
17
use telemetry:: { self , Telemetry } ;
18
+ use tokio_core:: net:: TcpStream ;
19
+ use tokio_core:: reactor:: Handle ;
20
+ use tokio_io:: { AsyncRead , AsyncWrite } ;
21
+ use tokio_io:: codec:: { Encoder , Decoder , Framed } ;
22
+ use tokio_proto:: pipeline:: { ClientProto , ClientService } ;
23
+ use tokio_proto:: TcpClient ;
24
+ use tokio_service:: Service ;
11
25
12
26
pub struct Host {
13
27
telemetry : Option < Telemetry > ,
14
- sock : Option < u32 > ,
15
28
}
16
29
30
+ pub struct RemoteHost {
31
+ inner : ClientService < TcpStream , JsonProto > ,
32
+ telemetry : Option < Telemetry > ,
33
+ }
34
+
35
+ struct JsonCodec ;
36
+ struct JsonProto ;
37
+
17
38
impl Host {
18
39
/// Create a new Host targeting the local machine.
19
40
pub fn local ( ) -> Result < Host > {
20
41
let mut host = Host {
21
42
telemetry : None ,
22
- sock : None
23
43
} ;
24
44
25
45
host. telemetry = Some ( telemetry:: load ( & host) ?) ;
26
46
27
47
Ok ( host)
28
48
}
29
49
50
+ /// Retrieve Telemetry
51
+ pub fn telemetry ( & self ) -> & Telemetry {
52
+ self . telemetry . as_ref ( ) . unwrap ( )
53
+ }
54
+
55
+ pub fn is_local ( & self ) -> bool {
56
+ true
57
+ }
58
+ }
59
+
60
+ impl RemoteHost {
30
61
/// Create a new Host connected to addr.
31
- pub fn connect ( _addr : & str ) -> Result < Host > {
32
- unimplemented ! ( ) ;
33
- // @todo Connect to sock...
62
+ pub fn connect ( addr : & SocketAddr , handle : & Handle ) -> Box < Future < Item = RemoteHost , Error = io:: Error > > {
63
+ let ret = TcpClient :: new ( JsonProto )
64
+ . connect ( addr, handle)
65
+ . map ( |client_service| {
66
+ RemoteHost {
67
+ inner : client_service,
68
+ telemetry : None ,
69
+ }
70
+ } ) ;
34
71
35
- // let mut host = Host {
36
- // telemetry: None,
37
- // sock: None
38
- // };
39
- //
40
- // let provider = telemetry::factory(&host)?;
41
- // host.telemetry = Some(provider.load()?);
42
- //
43
- // Ok(host)
72
+ Box :: new ( ret)
44
73
}
45
74
46
75
/// Retrieve Telemetry
@@ -49,6 +78,69 @@ impl Host {
49
78
}
50
79
51
80
pub fn is_local ( & self ) -> bool {
52
- self . sock . is_none ( )
81
+ false
82
+ }
83
+
84
+ pub fn run < T > ( & self , provider : RemoteProvider ) -> Box < Future < Item = T , Error = io:: Error > >
85
+ where for < ' de > T : Deserialize < ' de >
86
+ {
87
+ Box :: new ( self . inner . call ( provider)
88
+ . map ( |v| serde_json:: from_value :: < T > ( v) . unwrap ( ) ) )
89
+ }
90
+ }
91
+
92
+ impl Service for RemoteHost {
93
+ type Request = RemoteProvider ;
94
+ type Response = serde_json:: Value ;
95
+ type Error = io:: Error ;
96
+ type Future = Box < Future < Item = Self :: Response , Error = Self :: Error > > ;
97
+
98
+ fn call ( & self , req : Self :: Request ) -> Self :: Future {
99
+ Box :: new ( self . inner . call ( req) )
100
+ }
101
+ }
102
+
103
+ impl Decoder for JsonCodec {
104
+ type Item = serde_json:: Value ;
105
+ type Error = io:: Error ;
106
+
107
+ fn decode ( & mut self , buf : & mut BytesMut ) -> result:: Result < Option < Self :: Item > , Self :: Error > {
108
+ // Check to see if the frame contains a new line
109
+ if let Some ( n) = buf. as_ref ( ) . iter ( ) . position ( |b| * b == b'\n' ) {
110
+ // remove the serialized frame from the buffer.
111
+ let line = buf. split_to ( n) ;
112
+
113
+ // Also remove the '\n'
114
+ buf. split_to ( 1 ) ;
115
+
116
+ return Ok ( Some ( serde_json:: from_slice ( & line) . unwrap ( ) ) ) ;
117
+ }
118
+
119
+ Ok ( None )
120
+ }
121
+ }
122
+
123
+ impl Encoder for JsonCodec {
124
+ type Item = RemoteProvider ;
125
+ type Error = io:: Error ;
126
+
127
+ fn encode ( & mut self , provider : Self :: Item , buf : & mut BytesMut ) -> io:: Result < ( ) > {
128
+ let json = serde_json:: to_string ( & provider) . unwrap ( ) ;
129
+ buf. reserve ( json. len ( ) + 1 ) ;
130
+ buf. extend ( json. as_bytes ( ) ) ;
131
+ buf. put_u8 ( b'\n' ) ;
132
+
133
+ Ok ( ( ) )
134
+ }
135
+ }
136
+
137
+ impl < T : AsyncRead + AsyncWrite + ' static > ClientProto < T > for JsonProto {
138
+ type Request = RemoteProvider ;
139
+ type Response = serde_json:: Value ;
140
+ type Transport = Framed < T , JsonCodec > ;
141
+ type BindTransport = result:: Result < Self :: Transport , io:: Error > ;
142
+
143
+ fn bind_transport ( & self , io : T ) -> Self :: BindTransport {
144
+ Ok ( io. framed ( JsonCodec ) )
53
145
}
54
146
}
0 commit comments