-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[poc] socket: mimic MSG_PEEK by read for windows #18305
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -114,6 +114,16 @@ Api::IoCallUint64Result IoSocketHandleImpl::read(Buffer::Instance& buffer, | |
| if (max_length == 0) { | ||
| return Api::ioCallUint64ResultNoError(); | ||
| } | ||
| if constexpr (Event::PlatformDefaultTriggerType == Event::FileTriggerType::EmulatedEdge) { | ||
| if (buffer_->length() > 0) { | ||
| auto move_length = std::min(buffer_->length(), max_length); | ||
| buffer.move(*buffer_); | ||
| if (file_event_) { | ||
| file_event_->registerEventIfEmulatedEdge(Event::FileReadyType::Read); | ||
| } | ||
| return Api::IoCallUint64Result(move_length, Api::IoErrorPtr(nullptr, [](Api::IoError*) {})); | ||
| } | ||
| } | ||
| Buffer::Reservation reservation = buffer.reserveForRead(); | ||
| Api::IoCallUint64Result result = readv(std::min(reservation.length(), max_length), | ||
| reservation.slices(), reservation.numSlices()); | ||
|
|
@@ -502,6 +512,46 @@ Api::IoCallUint64Result IoSocketHandleImpl::recvmmsg(RawSliceArrays& slices, uin | |
| } | ||
|
|
||
| Api::IoCallUint64Result IoSocketHandleImpl::recv(void* buffer, size_t length, int flags) { | ||
| if constexpr (Event::PlatformDefaultTriggerType == Event::FileTriggerType::EmulatedEdge) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am wondering if we should have a dedicated peek function for this.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yea, agree with you. |
||
| // Mimic the MSG_PEEK by read data. | ||
| if (flags & MSG_PEEK) { | ||
| // Actually, this drain the data out of socket buffer. Although the `buffer_` may | ||
| // already has the enough data, but we have to drain the socket to ensure there is | ||
| // no more `Read` event. | ||
| Buffer::Reservation reservation = buffer_->reserveForRead(); | ||
| auto length_to_read = std::min(reservation.length(), length); | ||
| // TODO(soulxu): this should be in a while loop until eagain returned. | ||
| Api::IoCallUint64Result result = | ||
| readv(length_to_read, reservation.slices(), reservation.numSlices()); | ||
| uint64_t bytes_to_commit = result.ok() ? result.return_value_ : 0; | ||
| reservation.commit(bytes_to_commit); | ||
| if (file_event_) { | ||
| file_event_->registerEventIfEmulatedEdge(Event::FileReadyType::Read); | ||
| } | ||
| // The read failed, then we return the failure also. | ||
| if (bytes_to_commit == 0) { | ||
| return result; | ||
| } | ||
| auto copy_size = std::min(buffer_->length(), length); | ||
| buffer_->copyOut(0, copy_size, buffer); | ||
| return Api::IoCallUint64Result(copy_size, Api::IoErrorPtr(nullptr, [](Api::IoError*) {})); | ||
| ; | ||
| } else { | ||
| if (buffer_->length() > 0) { | ||
| auto copy_size = std::min(buffer_->length(), length); | ||
| buffer_->copyOut(0, copy_size, buffer); | ||
| buffer_->drain(copy_size); | ||
| if (copy_size < length) { | ||
| length = length - copy_size; | ||
| } else { | ||
| if (file_event_) { | ||
| file_event_->registerEventIfEmulatedEdge(Event::FileReadyType::Read); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general it is assumed that it is a responsibility of the caller to re-active the event if they expect more data unless the error is WOULD_BLOCK In the case of tls/proxy inspectors they should be able to determine that the data they currently have are not available to do their work and they should re-enable read. This is something that
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yea, same as the previous one, whether we should emulate all the cases. or we can just add assert here, assume people always read the data until WOULD_BLOCK return. |
||
| } | ||
| return Api::IoCallUint64Result(copy_size, Api::IoErrorPtr(nullptr, [](Api::IoError*) {})); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| const Api::SysCallSizeResult result = | ||
| Api::OsSysCallsSingleton::get().recv(fd_, buffer, length, flags); | ||
| auto io_result = sysCallResultToIoCallResult(result); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if this is needed. The caller should be reading until
EAGAINis returnedThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Emm...good point, should we emulate the case if the caller provides a small
max_length?