Unified · Split
| @@ -1,12 +1,17 @@ | |||
| 1 | use crate::client::http; | 1 | use crate::client::http; |
| 2 | use curl::easy::Easy2; | 2 | use curl::easy::Easy2; |
| 3 | use git_features::pipe; | 3 | use git_features::pipe; |
| 4 | use std::io::Read; | 4 | use std::{ |
| 5 | io, | ||
| 6 | io::Read, | ||
| 7 | sync::mpsc::{sync_channel, Receiver, SyncSender, TrySendError}, | ||
| 8 | }; | ||
| 5 | 9 | ||
| 6 | #[derive(Default)] | 10 | #[derive(Default)] |
| 7 | struct Handler { | 11 | struct 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 | ||
| 12 | impl curl::easy::Handler for Handler {} | 17 | impl 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 | ||
| 23 | struct Request { | ||
| 24 | url: String, | ||
| 25 | headers: curl::easy::List, | ||
| 26 | } | ||
| 27 | |||
| 28 | struct Response { | ||
| 29 | headers: pipe::Reader, | ||
| 30 | body: pipe::Reader, | ||
| 31 | upload_body: pipe::Writer, | ||
| 32 | } | ||
| 33 | |||
| 34 | fn 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 | |||
| 18 | impl Curl { | 97 | impl Curl { |
| 19 | pub fn new() -> Self { | 98 | pub fn new() -> Self { |
| 20 | Curl { | 99 | Curl { |