| 152 | |
| 153 | |
| 154 | Future<string> SocketImpl::recv(const Option<ssize_t>& size) |
| 155 | { |
| 156 | // Extend lifetime by holding onto a reference to ourself! |
| 157 | auto self = shared_from_this(); |
| 158 | |
| 159 | // Default chunk size to attempt to receive when nothing is |
| 160 | // specified represents roughly 16 pages. |
| 161 | static const size_t DEFAULT_CHUNK = 16 * os::pagesize(); |
| 162 | |
| 163 | const size_t chunk = (size.isNone() || size.get() < 0) |
| 164 | ? DEFAULT_CHUNK |
| 165 | : size.get(); |
| 166 | |
| 167 | boost::shared_array<char> data(new char[chunk]); |
| 168 | string buffer; |
| 169 | |
| 170 | return loop( |
| 171 | None(), |
| 172 | [=]() { |
| 173 | return self->recv(data.get(), chunk); |
| 174 | }, |
| 175 | [=](size_t length) mutable -> ControlFlow<string> { |
| 176 | if (length == 0) { // EOF. |
| 177 | // Return everything we've received thus far, a subsequent |
| 178 | // receive will return an empty string. |
| 179 | return Break(std::move(buffer)); |
| 180 | } |
| 181 | |
| 182 | buffer.append(data.get(), length); |
| 183 | |
| 184 | if (size.isNone()) { |
| 185 | // We've been asked just to return any data that we receive! |
| 186 | return Break(std::move(buffer)); |
| 187 | } else if (size.get() < 0) { |
| 188 | // We've been asked to receive until EOF so keep receiving |
| 189 | // since according to the 'length == 0' check above we |
| 190 | // haven't reached EOF yet. |
| 191 | return Continue(); |
| 192 | } else if ( |
| 193 | static_cast<string::size_type>(size.get()) > buffer.size()) { |
| 194 | // We've been asked to receive a particular amount of data and we |
| 195 | // haven't yet received that much data so keep receiving. |
| 196 | return Continue(); |
| 197 | } |
| 198 | |
| 199 | // We've received as much data as requested, so return that data! |
| 200 | return Break(std::move(buffer)); |
| 201 | }); |
| 202 | } |
| 203 | |
| 204 | |
| 205 | Future<Nothing> SocketImpl::send(const string& data) |