dccp sender: Keep polling until an entry becomes free (Gerrit Renker).
[paraslash.git] / dccp_send.c
index 6cd7fa4b8ca9d28d3c0b69c4966788a27a0d71a3..bdc7681e1de02469daaa0bc10698514eac563583 100644 (file)
@@ -79,7 +79,7 @@ static int dccp_open(void)
                return ret;
        listen_fd = ret;
 
-       bzero(&servaddr, sizeof(servaddr));
+       memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(conf.dccp_port_arg);
@@ -108,31 +108,26 @@ static void dccp_shutdown_client(struct dccp_client *dc)
        free(dc);
 }
 
-/** give up if write would block that many times */
-#define DCCP_WRITE_RETRIES 100
-
 static int dccp_write(int fd, const char *buf, size_t len)
 {
-       size_t size, written = 0;
-       int ret, retries = 0;
-again:
-       size = PARA_MIN(1024, len - written);
-       ret = write(fd, buf + written, size);
-       if (ret < 0) {
-               if (errno != EAGAIN || retries++ > DCCP_WRITE_RETRIES)
-                       goto err_out;
-               PARA_DEBUG_LOG("EAGAIN #%d@%zd/%zd\n", retries, written, len);
-               goto again;
+       size_t written = 0;
+       int ret = 0;
+
+       while (written < len) {
+               ret = write(fd, buf + written, PARA_MIN(1024, len - written));
+               /*
+                * Error handling: CCID3 has a sending wait queue which fills up and is
+                * emptied asynchronously. The EAGAIN case means that there is currently
+                * no space in the wait queue, but this can change at any moment and is
+                * thus not an error condition. Keep polling until an entry becomes free.
+                */
+               if (ret < 0 && errno == EAGAIN)
+                       continue;
+               if (ret < 0)
+                       return -E_DCCP_WRITE;
+               written += ret;
        }
-       retries = 0;
-       written += ret;
-       if (written >= len)
-               return written;
-       ret = write_ok(fd);
-       if (ret > 0)
-               goto again;
-err_out:
-       return -E_DCCP_WRITE;
+       return written;
 }
 
 static void dccp_send(long unsigned current_chunk,