Use WSARecv/WSASend instead of ReadFile/WriteFile. Fix check_status.
GitOrigin-RevId: bbfdf27d508f5c985b14bc13bd8549201ae1cb15
This commit is contained in:
parent
3e991d2464
commit
f4c85df878
@ -93,7 +93,7 @@ class ServerSocketFdImpl : private IOCP::Callback {
|
|||||||
bool close_flag_{false};
|
bool close_flag_{false};
|
||||||
std::atomic<int> refcnt_{1};
|
std::atomic<int> refcnt_{1};
|
||||||
bool is_read_active_{false};
|
bool is_read_active_{false};
|
||||||
OVERLAPPED read_overlapped_;
|
WSAOVERLAPPED read_overlapped_;
|
||||||
|
|
||||||
char close_overlapped_;
|
char close_overlapped_;
|
||||||
|
|
||||||
@ -126,17 +126,14 @@ class ServerSocketFdImpl : private IOCP::Callback {
|
|||||||
accept_socket_ = NativeFd(socket(socket_family_, SOCK_STREAM, 0));
|
accept_socket_ = NativeFd(socket(socket_family_, SOCK_STREAM, 0));
|
||||||
std::memset(&read_overlapped_, 0, sizeof(read_overlapped_));
|
std::memset(&read_overlapped_, 0, sizeof(read_overlapped_));
|
||||||
VLOG(fd) << get_native_fd().io_handle() << " start accept";
|
VLOG(fd) << get_native_fd().io_handle() << " start accept";
|
||||||
auto status = AcceptEx(get_native_fd().socket(), accept_socket_.socket(), addr_buf_, 0, MAX_ADDR_SIZE,
|
BOOL status = AcceptEx(get_native_fd().socket(), accept_socket_.socket(), addr_buf_, 0, MAX_ADDR_SIZE,
|
||||||
MAX_ADDR_SIZE, nullptr, &read_overlapped_);
|
MAX_ADDR_SIZE, nullptr, &read_overlapped_);
|
||||||
if (check_status(status, "Failed to accept connection")) {
|
if (status == TRUE || check_status("Failed to accept connection")) {
|
||||||
inc_refcnt();
|
inc_refcnt();
|
||||||
is_read_active_ = true;
|
is_read_active_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool check_status(DWORD status, Slice message) {
|
bool check_status(Slice message) {
|
||||||
if (status == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
auto last_error = WSAGetLastError();
|
auto last_error = WSAGetLastError();
|
||||||
if (last_error == ERROR_IO_PENDING) {
|
if (last_error == ERROR_IO_PENDING) {
|
||||||
return true;
|
return true;
|
||||||
@ -164,7 +161,7 @@ class ServerSocketFdImpl : private IOCP::Callback {
|
|||||||
get_poll_info().add_flags_from_poll(PollFlags::Error());
|
get_poll_info().add_flags_from_poll(PollFlags::Error());
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_iocp(Result<size_t> r_size, OVERLAPPED *overlapped) override {
|
void on_iocp(Result<size_t> r_size, WSAOVERLAPPED *overlapped) override {
|
||||||
// called from other thread
|
// called from other thread
|
||||||
if (dec_refcnt() || close_flag_) {
|
if (dec_refcnt() || close_flag_) {
|
||||||
return;
|
return;
|
||||||
@ -180,7 +177,7 @@ class ServerSocketFdImpl : private IOCP::Callback {
|
|||||||
return on_read();
|
return on_read();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overlapped == reinterpret_cast<OVERLAPPED *>(&close_overlapped_)) {
|
if (overlapped == reinterpret_cast<WSAOVERLAPPED *>(&close_overlapped_)) {
|
||||||
return on_close();
|
return on_close();
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -192,7 +189,7 @@ class ServerSocketFdImpl : private IOCP::Callback {
|
|||||||
}
|
}
|
||||||
void notify_iocp_close() {
|
void notify_iocp_close() {
|
||||||
VLOG(fd) << get_native_fd().io_handle() << " notify_close";
|
VLOG(fd) << get_native_fd().io_handle() << " notify_close";
|
||||||
IOCP::get()->post(0, this, reinterpret_cast<OVERLAPPED *>(&close_overlapped_));
|
IOCP::get()->post(0, this, reinterpret_cast<WSAOVERLAPPED *>(&close_overlapped_));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
void ServerSocketFdImplDeleter::operator()(ServerSocketFdImpl *impl) {
|
void ServerSocketFdImplDeleter::operator()(ServerSocketFdImpl *impl) {
|
||||||
|
@ -63,7 +63,7 @@ class SocketFdImpl : private IOCP::Callback {
|
|||||||
auto status = ConnectExPtr(get_native_fd().socket(), addr.get_sockaddr(), narrow_cast<int>(addr.get_sockaddr_len()),
|
auto status = ConnectExPtr(get_native_fd().socket(), addr.get_sockaddr(), narrow_cast<int>(addr.get_sockaddr_len()),
|
||||||
nullptr, 0, nullptr, &read_overlapped_);
|
nullptr, 0, nullptr, &read_overlapped_);
|
||||||
|
|
||||||
if (!check_status(status, "Failed to connect")) {
|
if (status == TRUE || !check_status("Failed to connect")) {
|
||||||
is_read_active_ = false;
|
is_read_active_ = false;
|
||||||
dec_refcnt();
|
dec_refcnt();
|
||||||
}
|
}
|
||||||
@ -131,21 +131,18 @@ class SocketFdImpl : private IOCP::Callback {
|
|||||||
bool is_read_active_{false};
|
bool is_read_active_{false};
|
||||||
ChainBufferWriter input_writer_;
|
ChainBufferWriter input_writer_;
|
||||||
ChainBufferReader input_reader_ = input_writer_.extract_reader();
|
ChainBufferReader input_reader_ = input_writer_.extract_reader();
|
||||||
OVERLAPPED read_overlapped_;
|
WSAOVERLAPPED read_overlapped_;
|
||||||
VectorQueue<Status> pending_errors_;
|
VectorQueue<Status> pending_errors_;
|
||||||
|
|
||||||
bool is_write_active_{false};
|
bool is_write_active_{false};
|
||||||
std::atomic<bool> is_write_waiting_{false};
|
std::atomic<bool> is_write_waiting_{false};
|
||||||
ChainBufferWriter output_writer_;
|
ChainBufferWriter output_writer_;
|
||||||
ChainBufferReader output_reader_ = output_writer_.extract_reader();
|
ChainBufferReader output_reader_ = output_writer_.extract_reader();
|
||||||
OVERLAPPED write_overlapped_;
|
WSAOVERLAPPED write_overlapped_;
|
||||||
|
|
||||||
char close_overlapped_;
|
char close_overlapped_;
|
||||||
|
|
||||||
bool check_status(DWORD status, Slice message) {
|
bool check_status(Slice message) {
|
||||||
if (status == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
auto last_error = WSAGetLastError();
|
auto last_error = WSAGetLastError();
|
||||||
if (last_error == ERROR_IO_PENDING) {
|
if (last_error == ERROR_IO_PENDING) {
|
||||||
return true;
|
return true;
|
||||||
@ -162,9 +159,12 @@ class SocketFdImpl : private IOCP::Callback {
|
|||||||
}
|
}
|
||||||
std::memset(&read_overlapped_, 0, sizeof(read_overlapped_));
|
std::memset(&read_overlapped_, 0, sizeof(read_overlapped_));
|
||||||
auto dest = input_writer_.prepare_append();
|
auto dest = input_writer_.prepare_append();
|
||||||
auto status =
|
WSABUF buf;
|
||||||
ReadFile(get_native_fd().io_handle(), dest.data(), narrow_cast<DWORD>(dest.size()), nullptr, &read_overlapped_);
|
buf.len = narrow_cast<ULONG>(dest.size());
|
||||||
if (check_status(status, "Failed to read from connection")) {
|
buf.buf = dest.data();
|
||||||
|
DWORD flags = 0;
|
||||||
|
int status = WSARecv(get_native_fd().socket(), &buf, 1, nullptr, &flags, &read_overlapped_, nullptr);
|
||||||
|
if (status == 0 || check_status("Failed to read from connection")) {
|
||||||
inc_refcnt();
|
inc_refcnt();
|
||||||
is_read_active_ = true;
|
is_read_active_ = true;
|
||||||
}
|
}
|
||||||
@ -189,15 +189,17 @@ class SocketFdImpl : private IOCP::Callback {
|
|||||||
}
|
}
|
||||||
auto dest = output_reader_.prepare_read();
|
auto dest = output_reader_.prepare_read();
|
||||||
std::memset(&write_overlapped_, 0, sizeof(write_overlapped_));
|
std::memset(&write_overlapped_, 0, sizeof(write_overlapped_));
|
||||||
auto status = WriteFile(get_native_fd().io_handle(), dest.data(), narrow_cast<DWORD>(dest.size()), nullptr,
|
WSABUF buf;
|
||||||
&write_overlapped_);
|
buf.len = narrow_cast<ULONG>(dest.size());
|
||||||
if (check_status(status, "Failed to write to connection")) {
|
buf.buf = const_cast<CHAR *>(dest.data());
|
||||||
|
int status = WSASend(get_native_fd().socket(), &buf, 1, nullptr, 0, &write_overlapped_, nullptr);
|
||||||
|
if (status == 0 || check_status("Failed to write to connection")) {
|
||||||
inc_refcnt();
|
inc_refcnt();
|
||||||
is_write_active_ = true;
|
is_write_active_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_iocp(Result<size_t> r_size, OVERLAPPED *overlapped) override {
|
void on_iocp(Result<size_t> r_size, WSAOVERLAPPED *overlapped) override {
|
||||||
// called from other thread
|
// called from other thread
|
||||||
if (dec_refcnt() || close_flag_) {
|
if (dec_refcnt() || close_flag_) {
|
||||||
VLOG(fd) << "ignore iocp (file is closing)";
|
VLOG(fd) << "ignore iocp (file is closing)";
|
||||||
@ -223,7 +225,7 @@ class SocketFdImpl : private IOCP::Callback {
|
|||||||
if (overlapped == &read_overlapped_) {
|
if (overlapped == &read_overlapped_) {
|
||||||
return on_read(size);
|
return on_read(size);
|
||||||
}
|
}
|
||||||
if (overlapped == reinterpret_cast<OVERLAPPED *>(&close_overlapped_)) {
|
if (overlapped == reinterpret_cast<WSAOVERLAPPED *>(&close_overlapped_)) {
|
||||||
return on_close();
|
return on_close();
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -277,6 +279,7 @@ class SocketFdImpl : private IOCP::Callback {
|
|||||||
info.set_native_fd({});
|
info.set_native_fd({});
|
||||||
}
|
}
|
||||||
bool dec_refcnt() {
|
bool dec_refcnt() {
|
||||||
|
VLOG(fd) << get_native_fd().io_handle() << " dec_refcnt from " << refcnt_;
|
||||||
if (--refcnt_ == 0) {
|
if (--refcnt_ == 0) {
|
||||||
delete this;
|
delete this;
|
||||||
return true;
|
return true;
|
||||||
@ -286,6 +289,7 @@ class SocketFdImpl : private IOCP::Callback {
|
|||||||
void inc_refcnt() {
|
void inc_refcnt() {
|
||||||
CHECK(refcnt_ != 0);
|
CHECK(refcnt_ != 0);
|
||||||
refcnt_++;
|
refcnt_++;
|
||||||
|
VLOG(fd) << get_native_fd().io_handle() << " inc_refcnt to " << refcnt_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_iocp_write() {
|
void notify_iocp_write() {
|
||||||
@ -293,11 +297,11 @@ class SocketFdImpl : private IOCP::Callback {
|
|||||||
IOCP::get()->post(0, this, nullptr);
|
IOCP::get()->post(0, this, nullptr);
|
||||||
}
|
}
|
||||||
void notify_iocp_close() {
|
void notify_iocp_close() {
|
||||||
IOCP::get()->post(0, this, reinterpret_cast<OVERLAPPED *>(&close_overlapped_));
|
IOCP::get()->post(0, this, reinterpret_cast<WSAOVERLAPPED *>(&close_overlapped_));
|
||||||
}
|
}
|
||||||
void notify_iocp_connected() {
|
void notify_iocp_connected() {
|
||||||
inc_refcnt();
|
inc_refcnt();
|
||||||
IOCP::get()->post(0, this, reinterpret_cast<OVERLAPPED *>(&read_overlapped_));
|
IOCP::get()->post(0, this, &read_overlapped_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ class UdpSocketFdImpl : private IOCP::Callback {
|
|||||||
bool is_send_active_{false};
|
bool is_send_active_{false};
|
||||||
bool is_send_waiting_{false};
|
bool is_send_waiting_{false};
|
||||||
VectorQueue<UdpMessage> send_queue_;
|
VectorQueue<UdpMessage> send_queue_;
|
||||||
OVERLAPPED send_overlapped_;
|
WSAOVERLAPPED send_overlapped_;
|
||||||
|
|
||||||
bool is_receive_active_{false};
|
bool is_receive_active_{false};
|
||||||
VectorQueue<UdpMessage> receive_queue_;
|
VectorQueue<UdpMessage> receive_queue_;
|
||||||
@ -174,14 +174,11 @@ class UdpSocketFdImpl : private IOCP::Callback {
|
|||||||
BufferSlice receive_buffer_;
|
BufferSlice receive_buffer_;
|
||||||
|
|
||||||
UdpMessage to_send_;
|
UdpMessage to_send_;
|
||||||
OVERLAPPED receive_overlapped_;
|
WSAOVERLAPPED receive_overlapped_;
|
||||||
|
|
||||||
char close_overlapped_;
|
char close_overlapped_;
|
||||||
|
|
||||||
bool check_status(DWORD status, Slice message) {
|
bool check_status(Slice message) {
|
||||||
if (status == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
auto last_error = WSAGetLastError();
|
auto last_error = WSAGetLastError();
|
||||||
if (last_error == ERROR_IO_PENDING) {
|
if (last_error == ERROR_IO_PENDING) {
|
||||||
return true;
|
return true;
|
||||||
@ -214,7 +211,7 @@ class UdpSocketFdImpl : private IOCP::Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto status = WSARecvMsgPtr(get_native_fd().socket(), &receive_message_, nullptr, &receive_overlapped_, nullptr);
|
auto status = WSARecvMsgPtr(get_native_fd().socket(), &receive_message_, nullptr, &receive_overlapped_, nullptr);
|
||||||
if (check_status(status, "receive")) {
|
if (status == 0 || check_status("WSARecvMsg failed")) {
|
||||||
inc_refcnt();
|
inc_refcnt();
|
||||||
is_receive_active_ = true;
|
is_receive_active_ = true;
|
||||||
}
|
}
|
||||||
@ -236,13 +233,13 @@ class UdpSocketFdImpl : private IOCP::Callback {
|
|||||||
UdpSocketSendHelper send_helper;
|
UdpSocketSendHelper send_helper;
|
||||||
send_helper.to_native(to_send_, message);
|
send_helper.to_native(to_send_, message);
|
||||||
auto status = WSASendMsg(get_native_fd().socket(), &message, 0, nullptr, &send_overlapped_, nullptr);
|
auto status = WSASendMsg(get_native_fd().socket(), &message, 0, nullptr, &send_overlapped_, nullptr);
|
||||||
if (check_status(status, "send")) {
|
if (status == 0 || check_status("WSASendMsg failed")) {
|
||||||
inc_refcnt();
|
inc_refcnt();
|
||||||
is_send_active_ = true;
|
is_send_active_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_iocp(Result<size_t> r_size, OVERLAPPED *overlapped) override {
|
void on_iocp(Result<size_t> r_size, WSAOVERLAPPED *overlapped) override {
|
||||||
// called from other thread
|
// called from other thread
|
||||||
if (dec_refcnt() || close_flag_) {
|
if (dec_refcnt() || close_flag_) {
|
||||||
VLOG(fd) << "ignore iocp (file is closing)";
|
VLOG(fd) << "ignore iocp (file is closing)";
|
||||||
@ -268,15 +265,14 @@ class UdpSocketFdImpl : private IOCP::Callback {
|
|||||||
if (overlapped == &receive_overlapped_) {
|
if (overlapped == &receive_overlapped_) {
|
||||||
return on_receive(size);
|
return on_receive(size);
|
||||||
}
|
}
|
||||||
if (overlapped == reinterpret_cast<OVERLAPPED *>(&close_overlapped_)) {
|
if (overlapped == reinterpret_cast<WSAOVERLAPPED *>(&close_overlapped_)) {
|
||||||
return on_close();
|
return on_close();
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_error(Status status) {
|
void on_error(Status status) {
|
||||||
VLOG(fd) << get_native_fd().io_handle() << " "
|
VLOG(fd) << get_native_fd().io_handle() << " on error " << status;
|
||||||
<< "on error " << status;
|
|
||||||
{
|
{
|
||||||
auto lock = lock_.lock();
|
auto lock = lock_.lock();
|
||||||
pending_errors_.push(std::move(status));
|
pending_errors_.push(std::move(status));
|
||||||
@ -346,11 +342,11 @@ class UdpSocketFdImpl : private IOCP::Callback {
|
|||||||
IOCP::get()->post(0, this, nullptr);
|
IOCP::get()->post(0, this, nullptr);
|
||||||
}
|
}
|
||||||
void notify_iocp_close() {
|
void notify_iocp_close() {
|
||||||
IOCP::get()->post(0, this, reinterpret_cast<OVERLAPPED *>(&close_overlapped_));
|
IOCP::get()->post(0, this, reinterpret_cast<WSAOVERLAPPED *>(&close_overlapped_));
|
||||||
}
|
}
|
||||||
void notify_iocp_connected() {
|
void notify_iocp_connected() {
|
||||||
inc_refcnt();
|
inc_refcnt();
|
||||||
IOCP::get()->post(0, this, reinterpret_cast<OVERLAPPED *>(&receive_overlapped_));
|
IOCP::get()->post(0, this, reinterpret_cast<WSAOVERLAPPED *>(&receive_overlapped_));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,8 +28,9 @@ void IOCP::loop() {
|
|||||||
while (true) {
|
while (true) {
|
||||||
DWORD bytes = 0;
|
DWORD bytes = 0;
|
||||||
ULONG_PTR key = 0;
|
ULONG_PTR key = 0;
|
||||||
OVERLAPPED *overlapped = nullptr;
|
WSAOVERLAPPED *overlapped = nullptr;
|
||||||
BOOL ok = GetQueuedCompletionStatus(iocp_handle_.io_handle(), &bytes, &key, &overlapped, 1000);
|
BOOL ok = GetQueuedCompletionStatus(iocp_handle_.io_handle(), &bytes, &key,
|
||||||
|
reinterpret_cast<OVERLAPPED **>(&overlapped), 1000);
|
||||||
if (bytes || key || overlapped) {
|
if (bytes || key || overlapped) {
|
||||||
// LOG(ERROR) << "Got iocp " << bytes << " " << key << " " << overlapped;
|
// LOG(ERROR) << "Got iocp " << bytes << " " << key << " " << overlapped;
|
||||||
}
|
}
|
||||||
@ -80,8 +81,9 @@ void IOCP::subscribe(const NativeFd &native_fd, Callback *callback) {
|
|||||||
CHECK(iocp_handle == iocp_handle_.io_handle()) << iocp_handle << " " << iocp_handle_.io_handle();
|
CHECK(iocp_handle == iocp_handle_.io_handle()) << iocp_handle << " " << iocp_handle_.io_handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IOCP::post(size_t size, Callback *callback, OVERLAPPED *overlapped) {
|
void IOCP::post(size_t size, Callback *callback, WSAOVERLAPPED *overlapped) {
|
||||||
PostQueuedCompletionStatus(iocp_handle_.io_handle(), DWORD(size), reinterpret_cast<ULONG_PTR>(callback), overlapped);
|
PostQueuedCompletionStatus(iocp_handle_.io_handle(), DWORD(size), reinterpret_cast<ULONG_PTR>(callback),
|
||||||
|
reinterpret_cast<OVERLAPPED *>(overlapped));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WineventPoll::init() {
|
void WineventPoll::init() {
|
||||||
|
@ -34,12 +34,12 @@ class IOCP final : public Context<IOCP> {
|
|||||||
class Callback {
|
class Callback {
|
||||||
public:
|
public:
|
||||||
virtual ~Callback() = default;
|
virtual ~Callback() = default;
|
||||||
virtual void on_iocp(Result<size_t> r_size, OVERLAPPED *overlapped) = 0;
|
virtual void on_iocp(Result<size_t> r_size, WSAOVERLAPPED *overlapped) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void subscribe(const NativeFd &fd, Callback *callback);
|
void subscribe(const NativeFd &fd, Callback *callback);
|
||||||
void post(size_t size, Callback *callback, OVERLAPPED *overlapped);
|
void post(size_t size, Callback *callback, WSAOVERLAPPED *overlapped);
|
||||||
void loop();
|
void loop();
|
||||||
void interrupt_loop();
|
void interrupt_loop();
|
||||||
void clear();
|
void clear();
|
||||||
|
Reference in New Issue
Block a user