mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-05 02:02:01 +00:00
fix sendfile for 10.5
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6185 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
fb2c608511
commit
6528728611
@ -630,6 +630,125 @@ apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
|
|||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
/*
|
||||||
|
int
|
||||||
|
sendfile(int fd, int s, off_t offset, off_t *len, struct sf_hdtr *hdtr,
|
||||||
|
int flags);
|
||||||
|
*/
|
||||||
|
apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
|
||||||
|
apr_hdtr_t * hdtr, apr_off_t * offset,
|
||||||
|
apr_size_t * len, apr_int32_t flags)
|
||||||
|
{
|
||||||
|
int rv, i;
|
||||||
|
struct sf_hdtr headerstruct;
|
||||||
|
apr_off_t bytes_to_send = *len;
|
||||||
|
|
||||||
|
/* Ignore flags for now. */
|
||||||
|
flags = 0;
|
||||||
|
|
||||||
|
if (!hdtr) {
|
||||||
|
hdtr = &no_hdtr;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(hdtr->numheaders){
|
||||||
|
for (i = 0; i < hdtr->numheaders; i++) {
|
||||||
|
bytes_to_send += hdtr->headers[i].iov_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else hdtr->headers=NULL; //for us having headers pointing to a valid buffer, but numheaders=0 constitues EINVAL..
|
||||||
|
}
|
||||||
|
|
||||||
|
headerstruct.headers = hdtr->headers;
|
||||||
|
headerstruct.hdr_cnt = hdtr->numheaders;
|
||||||
|
headerstruct.trailers = hdtr->trailers;
|
||||||
|
headerstruct.trl_cnt = hdtr->numtrailers;
|
||||||
|
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (sock->options & APR_INCOMPLETE_WRITE) {
|
||||||
|
apr_status_t arv;
|
||||||
|
sock->options &= ~APR_INCOMPLETE_WRITE;
|
||||||
|
arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
|
||||||
|
if (arv != APR_SUCCESS) {
|
||||||
|
*len = 0;
|
||||||
|
return arv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bytes_to_send) {
|
||||||
|
/* We won't dare call sendfile() if we don't have
|
||||||
|
* header or file bytes to send because bytes_to_send == 0
|
||||||
|
* means send the whole file.
|
||||||
|
*/
|
||||||
|
int lflags = fcntl(sock->socketdes,F_GETFL,0);
|
||||||
|
lflags &= ~O_NONBLOCK;
|
||||||
|
fcntl(sock->socketdes,F_SETFL,lflags);
|
||||||
|
rv = sendfile(file->filedes, /* file to be sent */
|
||||||
|
sock->socketdes, /* socket */
|
||||||
|
*offset, /* where in the file to start */
|
||||||
|
&bytes_to_send, /* number of bytes to send */
|
||||||
|
&headerstruct, /* Headers/footers */
|
||||||
|
flags); /* undefined, set to 0 */
|
||||||
|
lflags |= O_NONBLOCK;
|
||||||
|
fcntl(sock->socketdes,F_SETFL,lflags);
|
||||||
|
if (rv == -1) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
if (sock->timeout > 0) {
|
||||||
|
sock->options |= APR_INCOMPLETE_WRITE;
|
||||||
|
}
|
||||||
|
/* FreeBSD's sendfile can return -1/EAGAIN even if it
|
||||||
|
* sent bytes. Sanitize the result so we get normal EAGAIN
|
||||||
|
* semantics w.r.t. bytes sent.
|
||||||
|
*/
|
||||||
|
if (bytes_to_send) {
|
||||||
|
/* normal exit for a big file & non-blocking io */
|
||||||
|
(*len) = bytes_to_send;
|
||||||
|
return APR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { /* rv == 0 (or the kernel is broken) */
|
||||||
|
if (bytes_to_send == 0) {
|
||||||
|
/* Most likely the file got smaller after the stat.
|
||||||
|
* Return an error so the caller can do the Right Thing.
|
||||||
|
*/
|
||||||
|
(*len) = bytes_to_send;
|
||||||
|
return APR_EOF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* just trailer bytes... use writev()
|
||||||
|
*/
|
||||||
|
rv = writev(sock->socketdes,
|
||||||
|
hdtr->trailers,
|
||||||
|
hdtr->numtrailers);
|
||||||
|
if (rv > 0) {
|
||||||
|
bytes_to_send = rv;
|
||||||
|
rv = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bytes_to_send = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((rv == -1) && (errno == EAGAIN)
|
||||||
|
&& (sock->timeout > 0)) {
|
||||||
|
apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
|
||||||
|
if (arv != APR_SUCCESS) {
|
||||||
|
*len = 0;
|
||||||
|
return arv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (rv == -1 && (errno == EINTR || errno == EAGAIN));
|
||||||
|
|
||||||
|
(*len) = bytes_to_send;
|
||||||
|
if (rv == -1) {
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
return APR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#elif defined(__hpux) || defined(__hpux__)
|
#elif defined(__hpux) || defined(__hpux__)
|
||||||
|
|
||||||
/* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */
|
/* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user