]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/dsi/dsi_stream.c
Merge master
[netatalk.git] / libatalk / dsi / dsi_stream.c
index a2a5872224188681f9da53b513913be37fed48cc..ccb8b76eae25d4dc091448ab8dff81e58ee2039a 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <atalk/logger.h>
 #include <atalk/dsi.h>
-#include <netatalk/endian.h>
 #include <atalk/util.h>
 
 #define min(a,b)  ((a) < (b) ? (a) : (b))
@@ -125,7 +124,7 @@ static int dsi_peek(DSI *dsi)
 /* 
  * Return all bytes up to count from dsi->buffer if there are any buffered there
  */
-static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
+static size_t from_buf(DSI *dsi, uint8_t *buf, size_t count)
 {
     size_t nbe = 0;
 
@@ -160,7 +159,7 @@ static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
  *    Note: this may return fewer bytes then requested in count !!
  * 3. If the buffer was empty, read from the socket.
  */
-static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
+static ssize_t buf_read(DSI *dsi, uint8_t *buf, size_t count)
 {
     ssize_t len;
 
@@ -184,7 +183,7 @@ static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
  * Get "length" bytes from buffer and/or socket. In order to avoid frequent small reads
  * this tries to read larger chunks (8192 bytes) into a buffer.
  */
-static size_t dsi_buffered_stream_read(DSI *dsi, u_int8_t *data, const size_t length)
+static size_t dsi_buffered_stream_read(DSI *dsi, uint8_t *data, const size_t length)
 {
   size_t len;
   size_t buflen;
@@ -236,7 +235,7 @@ static void unblock_sig(DSI *dsi)
  * Communication error with the client, enter disconnected state
  *
  * 1. close the socket
- * 2. set the DSI_DISCONNECTED flag
+ * 2. set the DSI_DISCONNECTED flag, remove possible sleep flags
  *
  * @returns  0 if successfully entered disconnected state
  *          -1 if ppid is 1 which means afpd master died
@@ -246,7 +245,8 @@ int dsi_disconnect(DSI *dsi)
 {
     LOG(log_note, logtype_dsi, "dsi_disconnect: entering disconnected state");
     dsi->proto_close(dsi);          /* 1 */
-    dsi->flags |= DSI_DISCONNECTED; /* 2 */
+    dsi->flags &= ~(DSI_SLEEPING | DSI_EXTSLEEP); /* 2 */
+    dsi->flags |= DSI_DISCONNECTED;
     if (geteuid() == 0)
         return -1;
     return 0;
@@ -265,13 +265,13 @@ ssize_t dsi_stream_write(DSI *dsi, void *data, const size_t length, int mode)
   dsi->in_write++;
   written = 0;
 
-  LOG(log_maxdebug, logtype_dsi, "dsi_stream_write: sending %u bytes", length);
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_write(send: %zd bytes): START", length);
 
   if (dsi->flags & DSI_DISCONNECTED)
       return -1;
 
   while (written < length) {
-      len = send(dsi->socket, (u_int8_t *) data + written, length - written, flags);
+      len = send(dsi->socket, (uint8_t *) data + written, length - written, flags);
       if (len >= 0) {
           written += len;
           continue;
@@ -304,6 +304,7 @@ ssize_t dsi_stream_write(DSI *dsi, void *data, const size_t length, int mode)
   }
 
   dsi->write_count += written;
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_write(send: %zd bytes): END", length);
 
 exit:
   dsi->in_write--;
@@ -316,10 +317,12 @@ exit:
 #ifdef WITH_SENDFILE
 ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t length)
 {
+  int ret = 0;
   size_t written;
   ssize_t len;
+  off_t pos = offset;
 
-  LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sending %u bytes", length);
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file(send %zd bytes): START", length);
 
   if (dsi->flags & DSI_DISCONNECTED)
       return -1;
@@ -328,15 +331,24 @@ ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t le
   written = 0;
 
   while (written < length) {
-    len = sys_sendfile(dsi->socket, fromfd, &offset, length - written);
+    len = sys_sendfile(dsi->socket, fromfd, &pos, length - written);
         
     if (len < 0) {
       if (errno == EINTR)
           continue;
-      if (errno == EINVAL || errno == ENOSYS)
-          return -1;
-          
+      if (errno == EINVAL || errno == ENOSYS) {
+          ret = -1;
+          goto exit;
+      }          
       if (errno == EAGAIN || errno == EWOULDBLOCK) {
+#if defined(SOLARIS) || defined(FREEBSD)
+          if (pos > offset) {
+              /* we actually have sent sth., adjust counters and keep trying */
+              len = pos - offset;
+              written += len;
+              offset = pos;
+          }
+#endif
           if (dsi_peek(dsi)) {
               /* can't go back to blocking mode, exit, the next read
                  will return with an error and afpd will die.
@@ -350,15 +362,20 @@ ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t le
     }
     else if (!len) {
         /* afpd is going to exit */
-        errno = EIO;
-        return -1; /* I think we're at EOF here... */
+          ret = -1;
+          goto exit;
     }
     else 
         written += len;
   }
 
   dsi->write_count += written;
+
+exit:
   dsi->in_write--;
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sent: %zd", written);
+  if (ret != 0)
+      return -1;
   return written;
 }
 #endif
@@ -382,7 +399,7 @@ size_t dsi_stream_read(DSI *dsi, void *data, const size_t length)
 
   stored = 0;
   while (stored < length) {
-      len = buf_read(dsi, (u_int8_t *) data + stored, length - stored);
+      len = buf_read(dsi, (uint8_t *) data + stored, length - stored);
       if (len == -1 && (errno == EINTR || errno == EAGAIN)) {
           LOG(log_maxdebug, logtype_dsi, "dsi_stream_read: select read loop");
           continue;
@@ -390,8 +407,10 @@ size_t dsi_stream_read(DSI *dsi, void *data, const size_t length)
           stored += len;
       } else { /* eof or error */
           /* don't log EOF error if it's just after connect (OSX 10.3 probe) */
+#if 0
           if (errno == ECONNRESET)
               dsi->flags |= DSI_GOT_ECONNRESET;
+#endif
           if (len || stored || dsi->read_count) {
               if (! (dsi->flags & DSI_DISCONNECTED)) {
                   LOG(log_error, logtype_dsi, "dsi_stream_read: len:%d, %s",
@@ -420,8 +439,7 @@ int dsi_stream_send(DSI *dsi, void *buf, size_t length)
   size_t towrite;
   ssize_t len;
 
-  LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes",
-      length ? length : sizeof(block));
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): START", length);
 
   if (dsi->flags & DSI_DISCONNECTED)
       return 0;
@@ -436,6 +454,7 @@ int dsi_stream_send(DSI *dsi, void *buf, size_t length)
         sizeof(dsi->header.dsi_reserved));
 
   if (!length) { /* just write the header */
+      LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): DSI header, no data", sizeof(block));
     length = (dsi_stream_write(dsi, block, sizeof(block), 0) == sizeof(block));
     return length; /* really 0 on failure, 1 on success */
   }
@@ -479,52 +498,52 @@ int dsi_stream_send(DSI *dsi, void *buf, size_t length)
           iov[1].iov_len -= len;
       }
   }
+
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): END", length);
   
   unblock_sig(dsi);
   return 1;
 }
 
 
-/* ---------------------------------------
- * read data. function on success. 0 on failure. data length gets
- * stored in length variable. this should really use size_t's, but
- * that would require changes elsewhere. */
-int dsi_stream_receive(DSI *dsi, void *buf, const size_t ilength,
-                      size_t *rlength)
+/*!
+ * Read DSI command and data
+ *
+ * @param  dsi   (rw) DSI handle
+ *
+ * @return    DSI function on success, 0 on failure
+ */
+int dsi_stream_receive(DSI *dsi)
 {
   char block[DSI_BLOCKSIZ];
 
-  LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength);
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: START");
 
   if (dsi->flags & DSI_DISCONNECTED)
       return 0;
 
   /* read in the header */
-  if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block)) 
+  if (dsi_buffered_stream_read(dsi, (uint8_t *)block, sizeof(block)) != sizeof(block)) 
     return 0;
 
   dsi->header.dsi_flags = block[0];
   dsi->header.dsi_command = block[1];
-  /* FIXME, not the right place, 
-     but we get a server disconnect without reason in the log
-  */
-  if (!block[1]) {
-      LOG(log_error, logtype_dsi, "dsi_stream_receive: invalid packet, fatal");
+
+  if (dsi->header.dsi_command == 0)
       return 0;
-  }
 
-  memcpy(&dsi->header.dsi_requestID, block + 2, 
-        sizeof(dsi->header.dsi_requestID));
+  memcpy(&dsi->header.dsi_requestID, block + 2, sizeof(dsi->header.dsi_requestID));
   memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
   memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
-  memcpy(&dsi->header.dsi_reserved, block + 12,
-        sizeof(dsi->header.dsi_reserved));
+  memcpy(&dsi->header.dsi_reserved, block + 12, sizeof(dsi->header.dsi_reserved));
   dsi->clientID = ntohs(dsi->header.dsi_requestID);
   
   /* make sure we don't over-write our buffers. */
-  *rlength = min(ntohl(dsi->header.dsi_len), ilength);
-  if (dsi_stream_read(dsi, buf, *rlength) != *rlength
+  dsi->cmdlen = min(ntohl(dsi->header.dsi_len), DSI_CMDSIZ);
+  if (dsi_stream_read(dsi, dsi->commands, dsi->cmdlen) != dsi->cmdlen
     return 0;
 
+  LOG(log_debug, logtype_dsi, "dsi_stream_receive: DSI cmdlen: %zd", dsi->cmdlen);
+
   return block[1];
 }