mirror of
https://github.com/pocoproject/poco.git
synced 2025-02-21 14:42:51 +01:00
enh(Net): SocketImpl::sendFile() sends entire contents by repeatedly calling sendfile() if necessary
This commit is contained in:
parent
356124a3f6
commit
b9af97ceb3
@ -288,23 +288,27 @@ public:
|
||||
/// is by enabling the SO_OOBINLINE option.
|
||||
|
||||
virtual std::streamsize sendFile(Poco::FileInputStream& FileInputStream, std::streamoff offset = 0, std::streamsize count = 0);
|
||||
/// Sends the contents of a file in an optimized way, if possible.
|
||||
/// Sends the contents of a file over the socket, using operating
|
||||
/// system-specific APIs, if available. The socket must not have
|
||||
/// been set to non-blocking.
|
||||
///
|
||||
/// If count is != 0, sends the given number of bytes, otherwise
|
||||
/// sends all bytes, starting from the given offset.
|
||||
///
|
||||
/// On POSIX systems, this means using sendfile() or sendfile64().
|
||||
/// On Windows, this means using TransmitFile().
|
||||
/// On Linux, macOS and FreeBSD systems, the implementation
|
||||
/// uses sendfile() or sendfile64().
|
||||
/// On Windows, the implementation uses TransmitFile().
|
||||
///
|
||||
/// If neither is available, or the socket is a SecureSocketImpl()
|
||||
/// (secure() returns true), falls back to reading the file
|
||||
/// block by block and callind sendBytes().
|
||||
/// If neither sendfile() nor TransmitFile() is available,
|
||||
/// or the socket is a secure one (secure() returne true),
|
||||
/// falls back to reading the file block by block and calling sendBytes().
|
||||
///
|
||||
/// Returns the number of bytes sent, which may be
|
||||
/// less than the number of bytes specified.
|
||||
/// Returns the number of bytes sent, which should be the same
|
||||
/// as count, unless count is 0.
|
||||
///
|
||||
/// Throws NetException (or a subclass) in case of any errors.
|
||||
/// Also throws if the socket is non-blocking.
|
||||
/// Also throws a NetException if the socket has been set to
|
||||
/// non-blocking.
|
||||
|
||||
virtual int available();
|
||||
/// Returns the number of bytes available that can be read
|
||||
|
@ -269,23 +269,27 @@ public:
|
||||
/// is by enabling the SO_OOBINLINE option.
|
||||
|
||||
std::streamsize sendFile(Poco::FileInputStream& FileInputStream, std::streamoff offset = 0, std::streamsize count = 0);
|
||||
/// Sends the contents of a file in an optimized way, if possible.
|
||||
/// Sends the contents of a file over the socket, using operating
|
||||
/// system-specific APIs, if available. The socket must not have
|
||||
/// been set to non-blocking.
|
||||
///
|
||||
/// If count is != 0, sends the given number of bytes, otherwise
|
||||
/// sends all bytes, starting from the given offset.
|
||||
///
|
||||
/// On POSIX systems, this means using sendfile() or sendfile64().
|
||||
/// On Windows, this means using TransmitFile().
|
||||
/// On Linux, macOS and FreeBSD systems, the implementation
|
||||
/// uses sendfile() or sendfile64().
|
||||
/// On Windows, the implementation uses TransmitFile().
|
||||
///
|
||||
/// If neither is available, or the socket is a SecureSocketImpl()
|
||||
/// (secure() returns true), falls back to reading the file
|
||||
/// block by block and callind sendBytes().
|
||||
/// If neither sendfile() nor TransmitFile() is available,
|
||||
/// or the socket is a SecureStreamSocket (secure() returne true),
|
||||
/// falls back to reading the file block by block and calling sendBytes().
|
||||
///
|
||||
/// Returns the number of bytes sent, which may be
|
||||
/// less than the number of bytes specified.
|
||||
/// Returns the number of bytes sent, which should be the same
|
||||
/// as count, unless count is 0.
|
||||
///
|
||||
/// Throws NetException (or a subclass) in case of any errors.
|
||||
/// Also throws if the socket is non-blocking.
|
||||
/// Also throws a NetException if the socket has been set to
|
||||
/// non-blocking.
|
||||
|
||||
StreamSocket(SocketImpl* pImpl);
|
||||
/// Creates the Socket and attaches the given SocketImpl.
|
||||
|
@ -132,19 +132,8 @@ void HTTPServerResponseImpl::sendFile(const std::string& path, const std::string
|
||||
write(*_pStream);
|
||||
if (_pRequest && _pRequest->getMethod() != HTTPRequest::HTTP_HEAD)
|
||||
{
|
||||
#ifdef POCO_HAVE_SENDFILE
|
||||
_pStream->flush(); // flush the HTTP headers to the socket, required by HTTP 1.0 and above
|
||||
|
||||
std::streamsize sent = 0;
|
||||
std::streamoff offset = 0;
|
||||
while (sent < length)
|
||||
{
|
||||
offset = sent;
|
||||
sent += _session.socket().sendFile(istr, offset);
|
||||
}
|
||||
#else
|
||||
StreamCopier::copyStream(istr, *_pStream);
|
||||
#endif
|
||||
_session.socket().sendFile(istr);
|
||||
}
|
||||
}
|
||||
else throw OpenFileException(path);
|
||||
|
@ -1521,10 +1521,6 @@ namespace
|
||||
throw Poco::NotImplementedException("native sendfile not implemented for this platform");
|
||||
#endif
|
||||
#endif
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
{
|
||||
sent = 0;
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
}
|
||||
@ -1534,12 +1530,17 @@ std::streamsize SocketImpl::sendFileNative(FileInputStream& fileInputStream, std
|
||||
{
|
||||
FileIOS::NativeHandle fd = fileInputStream.nativeHandle();
|
||||
if (count == 0) count = fileInputStream.size() - offset;
|
||||
std::streamoff sent = 0;
|
||||
while (sent == 0)
|
||||
std::streamsize sent = 0;
|
||||
while (count > 0)
|
||||
{
|
||||
errno = 0;
|
||||
sent = sendFileUnix(_sockfd, fd, offset, count);
|
||||
if (sent < 0)
|
||||
std::streamoff rc = sendFileUnix(_sockfd, fd, offset, count);
|
||||
if (rc >= 0)
|
||||
{
|
||||
sent += rc;
|
||||
offset += rc;
|
||||
count -= rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
error(errno);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user