[Freeswitch-svn] [commit] r6185 - freeswitch/trunk/libs/apr/network_io/unix

Freeswitch SVN brian at freeswitch.org
Thu Nov 8 08:45:58 EST 2007


Author: brian
Date: Thu Nov  8 08:45:57 2007
New Revision: 6185

Modified:
   freeswitch/trunk/libs/apr/network_io/unix/sendrecv.c

Log:
fix sendfile for 10.5

Modified: freeswitch/trunk/libs/apr/network_io/unix/sendrecv.c
==============================================================================
--- freeswitch/trunk/libs/apr/network_io/unix/sendrecv.c	(original)
+++ freeswitch/trunk/libs/apr/network_io/unix/sendrecv.c	Thu Nov  8 08:45:57 2007
@@ -630,6 +630,125 @@
     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__)
 
 /* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */



More information about the Freeswitch-svn mailing list