Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

io: add a copy_bidirectional utility #3572

Merged
merged 19 commits into from Apr 12, 2021
Merged

Conversation

conblem
Copy link
Contributor

@conblem conblem commented Mar 2, 2021

This pull request is based on the work by @bdonlan i have implemented the requested changes of #3230.

Motivation

While there is a unidirectional copy utility currently, bidirectional copying between two streams (eg, proxying connections) is a bit tricky to do seamlessly and correctly due to the need to propagate EOFs and handle various error conditions.

Solution

This change adds a helper that can be used to, for example, glue together two TcpStreams and forward data across them.

@conblem conblem changed the title Bidi copy io: add a copy_bidirectional utility Mar 2, 2021
@conblem
Copy link
Contributor Author

conblem commented Mar 4, 2021

@Darksonn could you take a look at the changes if you find time. Maybe rerunning the CI will fix the build errors, as I don't think this is a error on my side.

@Darksonn
Copy link
Contributor

Darksonn commented Mar 4, 2021

I don't know when I'll have time to look over the changes, but I hit the button that reruns CI.

Copy link
Contributor

@Darksonn Darksonn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about the delay in reviewing this PR.

tokio/src/io/util/copy_bidirectional.rs Outdated Show resolved Hide resolved
tokio/src/io/util/copy_bidirectional.rs Outdated Show resolved Hide resolved
tokio/src/io/util/copy_bidirectional.rs Outdated Show resolved Hide resolved
tokio/src/io/util/copy_bidirectional.rs Outdated Show resolved Hide resolved
tokio/src/io/util/copy_bidirectional.rs Outdated Show resolved Hide resolved
tokio/src/io/util/copy_bidirectional.rs Outdated Show resolved Hide resolved
@Darksonn
Copy link
Contributor

The diff appears to have been messed up by the merge. Can you rebase the commits onto the current master and force push?

@conblem
Copy link
Contributor Author

conblem commented Mar 26, 2021

@Darksonn thanks for the quick feedback, I have added the comments. CI is failing on some unrelated / unchanged files, which is weird as the master branch seems to pass CI.

@Darksonn
Copy link
Contributor

The CI stuff will be fixed by #3647.

@Darksonn
Copy link
Contributor

You should be able to merge in master or rebase again to fix the CI failure.

@conblem
Copy link
Contributor Author

conblem commented Mar 26, 2021

Seems to be good now.

Comment on lines +55 to +58
while self.pos < self.cap {
let me = &mut *self;
let i = ready!(writer.as_mut().poll_write(cx, &me.buf[me.pos..me.cap]))?;
if i == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make sense to try to read more data if the write returns Pending when me.cap < 2048.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will look into this

@Darksonn Darksonn added A-tokio Area: The main tokio crate M-io Module: tokio/io labels Mar 29, 2021
Copy link
Contributor

@Darksonn Darksonn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will open an issue to make the improvement I suggested.

@rneswold
Copy link

rneswold commented Apr 12, 2021

Interestingly enough, some colleagues and I were recently comparing TCP proxy implementations we wrote. My Rust version used a pair of tokio::io::copy instances. The program was concise but didn't perform well compared to the Java implementation! There wasn't much I could tweak, but it seemed to me that, on a gigabit Ethernet link, transferring 2k at a time is suboptimal.

It doesn't appear that I can make the buffer bigger (and this PR seems to keep the 2k buffer size). But I admit I'm a novice and may have missed a detail in the API.

Is there a way to make the buffer bigger using this function? And if not, why was 2k chosen?

@Darksonn
Copy link
Contributor

No, there isn't any way of making the buffer bigger as it is now, but I wouldn't mind adding another method that takes a buffer size.

@cssivision
Copy link
Contributor

No, there isn't any way of making the buffer bigger as it is now, but I wouldn't mind adding another method that takes a buffer size.

I'm glad to add another method. but what about the function name? copy_with_buffer_size? any ideas?

@rneswold
Copy link

copy_with_buffer_size, copy_using_buffer_size, copy_using_size, ...

I guess I don't have a preference.

@Darksonn
Copy link
Contributor

Please open a new issue for discussing this.

RRRadicalEdward added a commit to RRRadicalEdward/tokio that referenced this pull request Apr 20, 2024
This is the same as `copy_bidirectional` but accepts the `a` -> `b` and `b` -> `a` buffers sizes.
`copy_bidirectional` uses 8Kb buffers under the hood which isn't
configurable. `copy_bidirectional_with_size` fixes it by allowing an
user to set its own sizes for underlying buffers.

Fixes: tokio-rs#6454.
Refs: tokio-rs#3572.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate M-io Module: tokio/io
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants