Apache Mesos
sendfile.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_OS_WINDOWS_SENDFILE_HPP__
14 #define __STOUT_OS_WINDOWS_SENDFILE_HPP__
15 
16 #include <stout/error.hpp>
17 #include <stout/result.hpp>
18 #include <stout/try.hpp>
19 #include <stout/windows.hpp> // For `winioctl.h`.
20 
22 
23 #include <stout/os/int_fd.hpp>
24 
25 namespace os {
26 
28  const int_fd& s, const int_fd& fd, size_t length, OVERLAPPED* overlapped)
29 {
30  // `::TransmitFile` can only send `INT_MAX - 1` bytes.
31  CHECK_LE(length, INT_MAX - 1);
32 
33  const BOOL result = ::TransmitFile(
34  s, // Sending socket.
35  fd, // File to be sent.
36  static_cast<DWORD>(length), // Number of bytes to be sent from the file.
37  0, // Bytes per send. 0 chooses system default.
38  overlapped, // Overlapped object with file offset.
39  nullptr, // Data before and after file send.
40  0); // Flags.
41 
42  const WindowsError error;
43  if (result == FALSE &&
44  (error.code == WSA_IO_PENDING || error.code == ERROR_IO_PENDING)) {
45  return None();
46  }
47 
48  if (result == FALSE) {
49  return error;
50  }
51 
52  return length;
53 }
54 
55 // Returns the amount of bytes written from the input file
56 // descriptor to the output socket.
57 // On error, `Try<ssize_t, SocketError>` contains the error.
59  const int_fd& s, const int_fd& fd, off_t offset, size_t length)
60 {
61  if (offset < 0) {
62  return SocketError(WSAEINVAL);
63  }
64 
65  // NOTE: We convert the `offset` here to avoid potential data loss
66  // in the type casting and bitshifting below.
67  const uint64_t offset_ = offset;
68 
69  const Try<OVERLAPPED> from_ =
71 
72  if (from_.isError()) {
73  return SocketError(from_.error());
74  }
75 
76  OVERLAPPED from = from_.get();
77  from.Offset = static_cast<DWORD>(offset_);
78  from.OffsetHigh = static_cast<DWORD>(offset_ >> 32);
79 
80  const Result<size_t> result = sendfile_async(s, fd, length, &from);
81  if (result.isError()) {
82  return SocketError(result.error());
83  }
84 
85  if (result.isSome()) {
86  return result.get();
87  }
88 
89  DWORD sent = 0;
90  DWORD flags = 0;
91  if (::WSAGetOverlappedResult(s, &from, &sent, TRUE, &flags) == TRUE) {
92  return sent;
93  }
94 
95  return SocketError();
96 }
97 
98 } // namespace os {
99 
100 #endif // __STOUT_OS_WINDOWS_SENDFILE_HPP__
T & get()&
Definition: try.hpp:80
Definition: check.hpp:33
static Result< T > error(const std::string &message)
Definition: result.hpp:54
Try< OVERLAPPED > init_overlapped_for_sync_io()
Definition: overlapped.hpp:30
Definition: error.hpp:108
Definition: posix_signalhandler.hpp:23
Definition: check.hpp:30
ErrnoError SocketError
Definition: error.hpp:33
const DWORD code
Definition: error.hpp:29
static Try error(const E &e)
Definition: try.hpp:43
Definition: none.hpp:27
bool isError() const
Definition: try.hpp:78
std::string error(const std::string &msg, uint32_t code)
T & get()&
Definition: result.hpp:116
Try< ssize_t, SocketError > sendfile(int s, int fd, off_t offset, size_t length)
Definition: sendfile.hpp:42
bool isSome() const
Definition: result.hpp:112
bool isError() const
Definition: result.hpp:114
int int_fd
Definition: int_fd.hpp:35
Result< size_t > sendfile_async(const int_fd &s, const int_fd &fd, size_t length, OVERLAPPED *overlapped)
Definition: sendfile.hpp:27
Definition: parse.hpp:33