History

[clone] first sketch of remote-curl, a way to transform curl into Read/Write

Sebastian Thiel committed 6 years ago

Commit 22b4b391 parent afe29961 file · +80 −1Browse files

Unified · Split

git-transport/src/client/http/curl.rs+80−1
@@ -1,12 +1,17 @@
1use crate::client::http;1use crate::client::http;
2use curl::easy::Easy2;2use curl::easy::Easy2;
3use git_features::pipe;3use git_features::pipe;
4use std::io::Read;4use std::{
5 io,
6 io::Read,
7 sync::mpsc::{sync_channel, Receiver, SyncSender, TrySendError},
8};
5 9
6#[derive(Default)]10#[derive(Default)]
7struct Handler {11struct Handler {
8 send_header: Option<pipe::Writer>,12 send_header: Option<pipe::Writer>,
9 send_data: Option<pipe::Writer>,13 send_data: Option<pipe::Writer>,
14 receive_body: Option<pipe::Reader>,
10}15}
11 16
12impl curl::easy::Handler for Handler {}17impl curl::easy::Handler for Handler {}
@@ -15,6 +20,80 @@ pub struct Curl { · 2 unmodified lines
15 handle: Easy2<Handler>,20 handle: Easy2<Handler>,
16}21}
17 22
23struct Request {
24 url: String,
25 headers: curl::easy::List,
26}
27
28struct Response {
29 headers: pipe::Reader,
30 body: pipe::Reader,
31 upload_body: pipe::Writer,
32}
33
34fn new_remote_curl() -> (
35 std::thread::JoinHandle<Result<(), curl::Error>>,
36 SyncSender<Request>,
37 Receiver<Response>,
38) {
39 let (req_send, req_recv) = sync_channel(0);
40 let (res_send, res_recv) = sync_channel(0);
41 let handle = std::thread::spawn(move || -> Result<(), curl::Error> {
42 let mut handle = Easy2::new(Handler::default());
43 for Request { url, headers } in req_recv {
44 handle.url(&url)?;
45 handle.http_headers(headers)?;
46
47 let (receive_data, receive_headers, send_body) = {
48 let handler = handle.get_mut();
49 let (send, receive_data) = pipe::unidirectional(1);
50 handler.send_data = Some(send);
51 let (send, receive_headers) = pipe::unidirectional(1);
52 handler.send_header = Some(send);
53 let (send_body, receive_body) = pipe::unidirectional(None);
54 handler.receive_body = Some(receive_body);
55 (receive_data, receive_headers, send_body)
56 };
57
58 if let Err(err) = handle.perform() {
59 let handler = handle.get_mut();
60 let err = Err(io::Error::new(io::ErrorKind::Other, err));
61 handler.receive_body.take();
62 if let Some(header) = handler.send_header.take() {
63 match header.channel.try_send(err) {
64 Ok(_) => {
65 handler.send_data.take();
66 }
67 Err(TrySendError::Disconnected(err)) | Err(TrySendError::Full(err)) => {
68 if let Some(body) = handler.send_data.take() {
69 body.channel.try_send(err).ok();
70 }
71 }
72 }
73 }
74 } else {
75 let handler = handle.get_mut();
76 handler.receive_body.take();
77 handler.send_header.take();
78 handler.send_data.take();
79 }
80
81 if res_send
82 .send(Response {
83 headers: receive_headers,
84 body: receive_data,
85 upload_body: send_body,
86 })
87 .is_err()
88 {
89 break;
90 }
91 }
92 Ok(())
93 });
94 (handle, req_send, res_recv)
95}
96
18impl Curl {97impl Curl {
19 pub fn new() -> Self {98 pub fn new() -> Self {
20 Curl {99 Curl {