1// 2// detail/impl/descriptor_ops.ipp 3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4// 5// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6// 7// Distributed under the Boost Software License, Version 1.0. (See accompanying 8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9// 10 11#ifndef BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP 12#define BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP 13 14#if defined(_MSC_VER) && (_MSC_VER >= 1200) 15# pragma once 16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18#include <boost/asio/detail/config.hpp> 19#include <cerrno> 20#include <boost/asio/detail/descriptor_ops.hpp> 21#include <boost/asio/error.hpp> 22 23#if !defined(BOOST_ASIO_WINDOWS) \ 24 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ 25 && !defined(__CYGWIN__) 26 27#include <boost/asio/detail/push_options.hpp> 28 29namespace boost { 30namespace asio { 31namespace detail { 32namespace descriptor_ops { 33 34int open(const char* path, int flags, boost::system::error_code& ec) 35{ 36 int result = ::open(path, flags); 37 get_last_error(ec, result < 0); 38 return result; 39} 40 41int close(int d, state_type& state, boost::system::error_code& ec) 42{ 43 int result = 0; 44 if (d != -1) 45 { 46 result = ::close(d); 47 get_last_error(ec, result < 0); 48 49 if (result != 0 50 && (ec == boost::asio::error::would_block 51 || ec == boost::asio::error::try_again)) 52 { 53 // According to UNIX Network Programming Vol. 1, it is possible for 54 // close() to fail with EWOULDBLOCK under certain circumstances. What 55 // isn't clear is the state of the descriptor after this error. The one 56 // current OS where this behaviour is seen, Windows, says that the socket 57 // remains open. Therefore we'll put the descriptor back into blocking 58 // mode and have another attempt at closing it. 59#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) 60 int flags = ::fcntl(d, F_GETFL, 0); 61 if (flags >= 0) 62 ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK); 63#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) 64 ioctl_arg_type arg = 0; 65 ::ioctl(d, FIONBIO, &arg); 66#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) 67 state &= ~non_blocking; 68 69 result = ::close(d); 70 get_last_error(ec, result < 0); 71 } 72 } 73 74 return result; 75} 76 77bool set_user_non_blocking(int d, state_type& state, 78 bool value, boost::system::error_code& ec) 79{ 80 if (d == -1) 81 { 82 ec = boost::asio::error::bad_descriptor; 83 return false; 84 } 85 86#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) 87 int result = ::fcntl(d, F_GETFL, 0); 88 get_last_error(ec, result < 0); 89 if (result >= 0) 90 { 91 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); 92 result = ::fcntl(d, F_SETFL, flag); 93 get_last_error(ec, result < 0); 94 } 95#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) 96 ioctl_arg_type arg = (value ? 1 : 0); 97 int result = ::ioctl(d, FIONBIO, &arg); 98 get_last_error(ec, result < 0); 99#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) 100 101 if (result >= 0) 102 { 103 if (value) 104 state |= user_set_non_blocking; 105 else 106 { 107 // Clearing the user-set non-blocking mode always overrides any 108 // internally-set non-blocking flag. Any subsequent asynchronous 109 // operations will need to re-enable non-blocking I/O. 110 state &= ~(user_set_non_blocking | internal_non_blocking); 111 } 112 return true; 113 } 114 115 return false; 116} 117 118bool set_internal_non_blocking(int d, state_type& state, 119 bool value, boost::system::error_code& ec) 120{ 121 if (d == -1) 122 { 123 ec = boost::asio::error::bad_descriptor; 124 return false; 125 } 126 127 if (!value && (state & user_set_non_blocking)) 128 { 129 // It does not make sense to clear the internal non-blocking flag if the 130 // user still wants non-blocking behaviour. Return an error and let the 131 // caller figure out whether to update the user-set non-blocking flag. 132 ec = boost::asio::error::invalid_argument; 133 return false; 134 } 135 136#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) 137 int result = ::fcntl(d, F_GETFL, 0); 138 get_last_error(ec, result < 0); 139 if (result >= 0) 140 { 141 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); 142 result = ::fcntl(d, F_SETFL, flag); 143 get_last_error(ec, result < 0); 144 } 145#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) 146 ioctl_arg_type arg = (value ? 1 : 0); 147 int result = ::ioctl(d, FIONBIO, &arg); 148 get_last_error(ec, result < 0); 149#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) 150 151 if (result >= 0) 152 { 153 if (value) 154 state |= internal_non_blocking; 155 else 156 state &= ~internal_non_blocking; 157 return true; 158 } 159 160 return false; 161} 162 163std::size_t sync_read(int d, state_type state, buf* bufs, 164 std::size_t count, bool all_empty, boost::system::error_code& ec) 165{ 166 if (d == -1) 167 { 168 ec = boost::asio::error::bad_descriptor; 169 return 0; 170 } 171 172 // A request to read 0 bytes on a stream is a no-op. 173 if (all_empty) 174 { 175 ec.assign(0, ec.category()); 176 return 0; 177 } 178 179 // Read some data. 180 for (;;) 181 { 182 // Try to complete the operation without blocking. 183 signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count)); 184 get_last_error(ec, bytes < 0); 185 186 // Check if operation succeeded. 187 if (bytes > 0) 188 return bytes; 189 190 // Check for EOF. 191 if (bytes == 0) 192 { 193 ec = boost::asio::error::eof; 194 return 0; 195 } 196 197 // Operation failed. 198 if ((state & user_set_non_blocking) 199 || (ec != boost::asio::error::would_block 200 && ec != boost::asio::error::try_again)) 201 return 0; 202 203 // Wait for descriptor to become ready. 204 if (descriptor_ops::poll_read(d, 0, ec) < 0) 205 return 0; 206 } 207} 208 209std::size_t sync_read1(int d, state_type state, void* data, 210 std::size_t size, boost::system::error_code& ec) 211{ 212 if (d == -1) 213 { 214 ec = boost::asio::error::bad_descriptor; 215 return 0; 216 } 217 218 // A request to read 0 bytes on a stream is a no-op. 219 if (size == 0) 220 { 221 ec.assign(0, ec.category()); 222 return 0; 223 } 224 225 // Read some data. 226 for (;;) 227 { 228 // Try to complete the operation without blocking. 229 signed_size_type bytes = ::read(d, data, size); 230 get_last_error(ec, bytes < 0); 231 232 // Check if operation succeeded. 233 if (bytes > 0) 234 return bytes; 235 236 // Check for EOF. 237 if (bytes == 0) 238 { 239 ec = boost::asio::error::eof; 240 return 0; 241 } 242 243 // Operation failed. 244 if ((state & user_set_non_blocking) 245 || (ec != boost::asio::error::would_block 246 && ec != boost::asio::error::try_again)) 247 return 0; 248 249 // Wait for descriptor to become ready. 250 if (descriptor_ops::poll_read(d, 0, ec) < 0) 251 return 0; 252 } 253} 254 255bool non_blocking_read(int d, buf* bufs, std::size_t count, 256 boost::system::error_code& ec, std::size_t& bytes_transferred) 257{ 258 for (;;) 259 { 260 // Read some data. 261 signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count)); 262 get_last_error(ec, bytes < 0); 263 264 // Check for end of stream. 265 if (bytes == 0) 266 { 267 ec = boost::asio::error::eof; 268 return true; 269 } 270 271 // Check if operation succeeded. 272 if (bytes > 0) 273 { 274 bytes_transferred = bytes; 275 return true; 276 } 277 278 // Retry operation if interrupted by signal. 279 if (ec == boost::asio::error::interrupted) 280 continue; 281 282 // Check if we need to run the operation again. 283 if (ec == boost::asio::error::would_block 284 || ec == boost::asio::error::try_again) 285 return false; 286 287 // Operation failed. 288 bytes_transferred = 0; 289 return true; 290 } 291} 292 293bool non_blocking_read1(int d, void* data, std::size_t size, 294 boost::system::error_code& ec, std::size_t& bytes_transferred) 295{ 296 for (;;) 297 { 298 // Read some data. 299 signed_size_type bytes = ::read(d, data, size); 300 get_last_error(ec, bytes < 0); 301 302 // Check for end of stream. 303 if (bytes == 0) 304 { 305 ec = boost::asio::error::eof; 306 return true; 307 } 308 309 // Check if operation succeeded. 310 if (bytes > 0) 311 { 312 bytes_transferred = bytes; 313 return true; 314 } 315 316 // Retry operation if interrupted by signal. 317 if (ec == boost::asio::error::interrupted) 318 continue; 319 320 // Check if we need to run the operation again. 321 if (ec == boost::asio::error::would_block 322 || ec == boost::asio::error::try_again) 323 return false; 324 325 // Operation failed. 326 bytes_transferred = 0; 327 return true; 328 } 329} 330 331std::size_t sync_write(int d, state_type state, const buf* bufs, 332 std::size_t count, bool all_empty, boost::system::error_code& ec) 333{ 334 if (d == -1) 335 { 336 ec = boost::asio::error::bad_descriptor; 337 return 0; 338 } 339 340 // A request to write 0 bytes on a stream is a no-op. 341 if (all_empty) 342 { 343 ec.assign(0, ec.category()); 344 return 0; 345 } 346 347 // Write some data. 348 for (;;) 349 { 350 // Try to complete the operation without blocking. 351 signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count)); 352 get_last_error(ec, bytes < 0); 353 354 // Check if operation succeeded. 355 if (bytes > 0) 356 return bytes; 357 358 // Operation failed. 359 if ((state & user_set_non_blocking) 360 || (ec != boost::asio::error::would_block 361 && ec != boost::asio::error::try_again)) 362 return 0; 363 364 // Wait for descriptor to become ready. 365 if (descriptor_ops::poll_write(d, 0, ec) < 0) 366 return 0; 367 } 368} 369 370std::size_t sync_write1(int d, state_type state, const void* data, 371 std::size_t size, boost::system::error_code& ec) 372{ 373 if (d == -1) 374 { 375 ec = boost::asio::error::bad_descriptor; 376 return 0; 377 } 378 379 // A request to write 0 bytes on a stream is a no-op. 380 if (size == 0) 381 { 382 ec.assign(0, ec.category()); 383 return 0; 384 } 385 386 // Write some data. 387 for (;;) 388 { 389 // Try to complete the operation without blocking. 390 signed_size_type bytes = ::write(d, data, size); 391 get_last_error(ec, bytes < 0); 392 393 // Check if operation succeeded. 394 if (bytes > 0) 395 return bytes; 396 397 // Operation failed. 398 if ((state & user_set_non_blocking) 399 || (ec != boost::asio::error::would_block 400 && ec != boost::asio::error::try_again)) 401 return 0; 402 403 // Wait for descriptor to become ready. 404 if (descriptor_ops::poll_write(d, 0, ec) < 0) 405 return 0; 406 } 407} 408 409bool non_blocking_write(int d, const buf* bufs, std::size_t count, 410 boost::system::error_code& ec, std::size_t& bytes_transferred) 411{ 412 for (;;) 413 { 414 // Write some data. 415 signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count)); 416 get_last_error(ec, bytes < 0); 417 418 // Check if operation succeeded. 419 if (bytes >= 0) 420 { 421 bytes_transferred = bytes; 422 return true; 423 } 424 425 // Retry operation if interrupted by signal. 426 if (ec == boost::asio::error::interrupted) 427 continue; 428 429 // Check if we need to run the operation again. 430 if (ec == boost::asio::error::would_block 431 || ec == boost::asio::error::try_again) 432 return false; 433 434 // Operation failed. 435 bytes_transferred = 0; 436 return true; 437 } 438} 439 440bool non_blocking_write1(int d, const void* data, std::size_t size, 441 boost::system::error_code& ec, std::size_t& bytes_transferred) 442{ 443 for (;;) 444 { 445 // Write some data. 446 signed_size_type bytes = ::write(d, data, size); 447 get_last_error(ec, bytes < 0); 448 449 // Check if operation succeeded. 450 if (bytes >= 0) 451 { 452 bytes_transferred = bytes; 453 return true; 454 } 455 456 // Retry operation if interrupted by signal. 457 if (ec == boost::asio::error::interrupted) 458 continue; 459 460 // Check if we need to run the operation again. 461 if (ec == boost::asio::error::would_block 462 || ec == boost::asio::error::try_again) 463 return false; 464 465 // Operation failed. 466 bytes_transferred = 0; 467 return true; 468 } 469} 470 471int ioctl(int d, state_type& state, long cmd, 472 ioctl_arg_type* arg, boost::system::error_code& ec) 473{ 474 if (d == -1) 475 { 476 ec = boost::asio::error::bad_descriptor; 477 return -1; 478 } 479 480 int result = ::ioctl(d, cmd, arg); 481 get_last_error(ec, result < 0); 482 483 if (result >= 0) 484 { 485 // When updating the non-blocking mode we always perform the ioctl syscall, 486 // even if the flags would otherwise indicate that the descriptor is 487 // already in the correct state. This ensures that the underlying 488 // descriptor is put into the state that has been requested by the user. If 489 // the ioctl syscall was successful then we need to update the flags to 490 // match. 491 if (cmd == static_cast<long>(FIONBIO)) 492 { 493 if (*arg) 494 { 495 state |= user_set_non_blocking; 496 } 497 else 498 { 499 // Clearing the non-blocking mode always overrides any internally-set 500 // non-blocking flag. Any subsequent asynchronous operations will need 501 // to re-enable non-blocking I/O. 502 state &= ~(user_set_non_blocking | internal_non_blocking); 503 } 504 } 505 } 506 507 return result; 508} 509 510int fcntl(int d, int cmd, boost::system::error_code& ec) 511{ 512 if (d == -1) 513 { 514 ec = boost::asio::error::bad_descriptor; 515 return -1; 516 } 517 518 int result = ::fcntl(d, cmd); 519 get_last_error(ec, result < 0); 520 return result; 521} 522 523int fcntl(int d, int cmd, long arg, boost::system::error_code& ec) 524{ 525 if (d == -1) 526 { 527 ec = boost::asio::error::bad_descriptor; 528 return -1; 529 } 530 531 int result = ::fcntl(d, cmd, arg); 532 get_last_error(ec, result < 0); 533 return result; 534} 535 536int poll_read(int d, state_type state, boost::system::error_code& ec) 537{ 538 if (d == -1) 539 { 540 ec = boost::asio::error::bad_descriptor; 541 return -1; 542 } 543 544 pollfd fds; 545 fds.fd = d; 546 fds.events = POLLIN; 547 fds.revents = 0; 548 int timeout = (state & user_set_non_blocking) ? 0 : -1; 549 int result = ::poll(&fds, 1, timeout); 550 get_last_error(ec, result < 0); 551 if (result == 0) 552 if (state & user_set_non_blocking) 553 ec = boost::asio::error::would_block; 554 return result; 555} 556 557int poll_write(int d, state_type state, boost::system::error_code& ec) 558{ 559 if (d == -1) 560 { 561 ec = boost::asio::error::bad_descriptor; 562 return -1; 563 } 564 565 pollfd fds; 566 fds.fd = d; 567 fds.events = POLLOUT; 568 fds.revents = 0; 569 int timeout = (state & user_set_non_blocking) ? 0 : -1; 570 int result = ::poll(&fds, 1, timeout); 571 get_last_error(ec, result < 0); 572 if (result == 0) 573 if (state & user_set_non_blocking) 574 ec = boost::asio::error::would_block; 575 return result; 576} 577 578int poll_error(int d, state_type state, boost::system::error_code& ec) 579{ 580 if (d == -1) 581 { 582 ec = boost::asio::error::bad_descriptor; 583 return -1; 584 } 585 586 pollfd fds; 587 fds.fd = d; 588 fds.events = POLLPRI | POLLERR | POLLHUP; 589 fds.revents = 0; 590 int timeout = (state & user_set_non_blocking) ? 0 : -1; 591 int result = ::poll(&fds, 1, timeout); 592 get_last_error(ec, result < 0); 593 if (result == 0) 594 if (state & user_set_non_blocking) 595 ec = boost::asio::error::would_block; 596 return result; 597} 598 599} // namespace descriptor_ops 600} // namespace detail 601} // namespace asio 602} // namespace boost 603 604#include <boost/asio/detail/pop_options.hpp> 605 606#endif // !defined(BOOST_ASIO_WINDOWS) 607 // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) 608 // && !defined(__CYGWIN__) 609 610#endif // BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP 611