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

Add stream_id accessors to public API types #292

Merged
merged 6 commits into from Jul 13, 2018
Merged

Conversation

hawkw
Copy link
Collaborator

@hawkw hawkw commented Jul 9, 2018

Problem:

Applications may want to access the underlying h2 stream ID for
diagnostics, etc. Stream IDs were not previously exposed in public APIs.

Solution:

The frame::StreamId type is now publically exported and has RustDoc
comments. The public API types SendStream, RecvStream,
ReleaseCapacity, client::ResponseFuture, and server::SendResponse
now all have stream_id methods which return the stream ID of the
corresponding stream.

Closes #289.

Signed-off-by: Eliza Weisman eliza@buoyant.io

hawkw added 3 commits July 9, 2018 10:39
This will be necessary to add similar accessors to the public
API types that wrap these.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
The types `SendStream`, `RecvStream`, `ReleaseCapacity`,
`client::ResponseFuture`, and `server::SendResponse` now all have
`stream_id` methods which return the stream ID of the corresponding
stream.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
@hawkw hawkw self-assigned this Jul 9, 2018
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
@hawkw hawkw changed the title Eliza/expose stream Add stream_id accessors to public API types Jul 9, 2018
pub const ZERO: StreamId = StreamId(0);

/// The maximum allowed stream ID.
pub const MAX: StreamId = StreamId(u32::MAX >> 1);

/// Parse the stream ID
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm not sure if this function should be publicly exposed or not (perhaps it should be pub(crate) instead?)

pub fn is_zero(&self) -> bool {
self.0 == 0
}

/// Returns the next stream ID initiated by the same peer as this stream
/// ID, or an error if incrementing this stream ID would overflow the
/// maximum.
pub fn next_id(&self) -> Result<StreamId, StreamIdOverflow> {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Again, I'm not sure whether or not we want users of the library to be able to construct their own StreamIds. It seems harmless but I'm not sure if there's any use-case for it. Perhaps this should be pub(crate)?


pub fn stream_id(&self) -> StreamId {
self.inner.lock()
.unwrap()
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought unwrapping this was probably reasonable, rather than returning a Result, since if the mutex on the stream store is poisoned, we're in a pretty bad state (and the other functions on StreamRef also unwrap).

@seanmonstar
Copy link
Member

Yea, I'm also a little uncertain about exposing the StreamId type directly... Would it be more conservative to simply expose a u32 instead?

@hawkw
Copy link
Collaborator Author

hawkw commented Jul 9, 2018

@seanmonstar

Yea, I'm also a little uncertain about exposing the StreamId type directly... Would it be more conservative to simply expose a u32 instead?

I'm unsure...I think the newtype better expresses intent, and the is_client_initiated/is_server_initiated functions might potentially be useful. Personally, I think if we're concerned about exposing this type, restricting the constructors to pub(crate) is the right thing to do, but I could be convinced otherwise.

@carllerche
Copy link
Collaborator

@seanmonstar Exposing a new type would be more conservative than u32. It could be another StreamId type that doesn't have any additional fns on it?

@seanmonstar
Copy link
Member

True, a public StreamId that isn't the same as frame::StreamId. Then, we don't have to worry about any traits that are implemented for frame::StreamId, and down the line, its backwards compatible to just change to directly exporting frame::StreamId.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
@hawkw
Copy link
Collaborator Author

hawkw commented Jul 9, 2018

@seanmonstar WDYT of 557435c?

@seanmonstar
Copy link
Member

Looks good to me, if we also put pub(crate) on the internal one, to save us from any accidental exposure.

@hawkw
Copy link
Collaborator Author

hawkw commented Jul 9, 2018

@seanmonstar

Looks good to me, if we also put pub(crate) on the internal one, to save us from any accidental exposure.

Will do. Note that making frame::StreamId pub(crate) means that we also have to change all pub functions taking one (including those which are in private modules and thus not exported) explicitly pub(crate) as well, to placate the compiler:

error[E0446]: private type `frame::stream_id::StreamId` in public interface
  --> src/frame/data.rs:28:5
   |
28 | /     pub fn new(stream_id: StreamId, payload: T) -> Self {
29 | |         assert!(!stream_id.is_zero());
30 | |
31 | |         Data {
...  |
36 | |         }
37 | |     }
   | |_____^ can't leak private type

...and so on.

@hawkw
Copy link
Collaborator Author

hawkw commented Jul 9, 2018

Actually, nevermind; the fact that a lot of these types are publically-exposed if the unstable feature is set complicates this a bit. If we want the internal frame::StreamId to be pub(crate), then we'll have to have separate #[cfg("unstable")] pub versions of pretty much every function that takes a frame::StreamId. I'm not sure whether or not having it be pub(crate) is worth that, WDYT?

@seanmonstar
Copy link
Member

Hmph. I'm not even particularly sure what the unstable feature is really for, so I'll defer the final decision to @carllerche.

@hawkw
Copy link
Collaborator Author

hawkw commented Jul 9, 2018

@seanmonstar

I'm not even particularly sure what the unstable feature is really for

I believe it's mainly used so that the test support crate can access things that would otherwise not be public.

@carllerche
Copy link
Collaborator

Yes, it is for the test stuff.

That being said, with the introduction of tests in a sub crate, there is most likely a way to get rid of that feature flag.

@hawkw
Copy link
Collaborator Author

hawkw commented Jul 10, 2018

That being said, with the introduction of tests in a sub crate, there is most likely a way to get rid of that feature flag.

Okay. That seems out of scope for this branch, though?

@carllerche
Copy link
Collaborator

yes

@carllerche
Copy link
Collaborator

To comment on this issue, I'm OK exposing the stream ID where appropriate, but it should be a new type StreamId that has as few fns on it as possible.

@hawkw
Copy link
Collaborator Author

hawkw commented Jul 11, 2018

@carllerche

To comment on this issue, I'm OK exposing the stream ID where appropriate, but it should be a new type StreamId that has as few fns on it as possible.

That's what this branch does as of commit 557435c --- that commit adds a separate share::StreamId type for externally exposing stream IDs, distinct from frame::StreamId.

The conversation @seanmonstar and I were having was about the fact that the frame::StreamId type (the internal StreamId type) is currently declared as pub (and was before I opened this branch), but the module it's declared in is usually not exported, unless the unstable feature is set. @seanmonstar requested that it be declared as pub(crate) instead so that it's not accidentally exposed, but doing so would add a lot of additional complexity if we still wanted that type to be publicly exposed when the feature flag is set.

src/share.rs Outdated
/// new stream.
///
/// [Section 5.1.1]: https://tools.ietf.org/html/rfc7540#section-5.1.1
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would recommend removing Copy. I'd also remove Ord and PartialOrd unless there is a case to keep them.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The issue prompting this change (#289) states that:

I'd expect h2::StreamId to implement at least copy and comparison traits.

I'm not sure whether or not @olix0r has any specific rationale or use-case behind implementing those traits, though?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Clone would make more sense. Copy is pretty strong and adds a forwards compat hazard.

@hawkw
Copy link
Collaborator Author

hawkw commented Jul 12, 2018

Build failure for 2d63ed4 was due to a connection issue downloading h2spec, so I've restarted it.

@hawkw hawkw merged commit f3806d5 into master Jul 13, 2018
hawkw added a commit to tower-rs/tower-h2 that referenced this pull request Aug 2, 2018
This branch adds an accessor for the stream ID to `RecvBody`. It also
updates the h2 dependency to v0.1.11, as it requires hyperium/h2#292.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
@carllerche carllerche deleted the eliza/expose-stream-id branch October 16, 2018 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants