]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/util/socket.c
Hangs in Netatalk which causes it to stop responding to connections
[netatalk.git] / libatalk / util / socket.c
index c7ef534a7e556567bda75e22eb3048a4616816ae..60768a618708488e52160c62ea91b69b13aa6b4e 100644 (file)
@@ -503,113 +503,112 @@ EC_CLEANUP:
     EC_EXIT;
 }
 
-/*!
- * Add a fd to a dynamic pollfd array that is allocated and grown as needed
- *
- * This uses an additional array of struct polldata which stores type information
- * (enum fdtype) and a pointer to anciliary user data.
- *
- * 1. Allocate the arrays with the size of "maxconns" if *fdsetp is NULL.
- * 2. Fill in both array elements and increase count of used elements
- * 
- * @param maxconns    (r)  maximum number of connections, determines array size
- * @param fdsetp      (rw) pointer to callers pointer to the pollfd array
- * @param polldatap   (rw) pointer to callers pointer to the polldata array
- * @param fdset_usedp (rw) pointer to an int with the number of used elements
- * @param fdset_sizep (rw) pointer to an int which stores the array sizes
- * @param fd          (r)  file descriptor to add to the arrays
- * @param fdtype      (r)  type of fd, currently IPC_FD or LISTEN_FD
- * @param data        (rw) pointer to data the caller want to associate with an fd
- */
-void fdset_add_fd(int maxconns,
-                  struct pollfd **fdsetp,
-                  struct polldata **polldatap,
-                  int *fdset_usedp,
-                  int *fdset_sizep,
-                  int fd,
-                  enum fdtype fdtype,
-                  void *data)
+/**
+ * Allocate and initialize atalk socket event struct
+ **/
+struct asev *asev_init(int max)
 {
-    struct pollfd *fdset = *fdsetp;
-    struct polldata *polldata = *polldatap;
-    int fdset_size = *fdset_sizep;
+    struct asev *asev = calloc(1, sizeof(struct asev));
+
+    if (asev == NULL) {
+        return NULL;
+    }
 
-    LOG(log_debug, logtype_default, "fdset_add_fd: adding fd %i in slot %i", fd, *fdset_usedp);
+    /* Initialize with space for all possibly active fds */
+    asev->fdset = calloc(max, sizeof(struct pollfd));
+    asev->data = calloc(max, sizeof(struct asev_data));
 
-    if (fdset == NULL) { /* 1 */
-        /* Initialize with space for all possibly active fds */
-        fdset = calloc(maxconns, sizeof(struct pollfd));
-        if (! fdset)
-            exit(EXITERR_SYS);
+    if (asev->fdset == NULL || asev->data == NULL) {
+        free(asev->fdset);
+        free(asev->data);
+        free(asev);
+        return NULL;
+    }
 
-        polldata = calloc(maxconns, sizeof(struct polldata));
-        if (! polldata)
-            exit(EXITERR_SYS);
+    asev->max = max;
+    asev->used = 0;
 
-        fdset_size = maxconns;
+    return asev;
+}
 
-        *fdset_sizep = fdset_size;
-        *fdsetp = fdset;
-        *polldatap = polldata;
+/**
+ * Add a fd to a dynamic pollfd array and associated data array
+ *
+ * This uses an additional array of struct polldata which stores type
+ * information (enum fdtype) and a pointer to anciliary user data.
+ **/
+bool asev_add_fd(struct asev *asev,
+                 int fd,
+                 enum asev_fdtype fdtype,
+                 void *private)
+{
+    if (asev == NULL) {
+        return false;
+    }
 
-        LOG(log_debug, logtype_default, "fdset_add_fd: initialized with space for %i conncections", 
-            maxconns);
+    if (!(asev->used < asev->max)) {
+        return false;
     }
 
-    /* 2 */
-    fdset[*fdset_usedp].fd = fd;
-    fdset[*fdset_usedp].events = POLLIN;
-    polldata[*fdset_usedp].fdtype = fdtype;
-    polldata[*fdset_usedp].data = data;
-    (*fdset_usedp)++;
+    asev->fdset[asev->used].fd = fd;
+    asev->fdset[asev->used].events = POLLIN;
+    asev->data[asev->used].fdtype = fdtype;
+    asev->data[asev->used].private = private;
+    asev->used++;
+
+    return true;
 }
 
-/*!
- * Remove a fd from our pollfd array
- *
- * 1. Search fd
- * 2a Matched last (or only) in the set ? null it and return
- * 2b If we remove the last array elemnt, just decrease count
- * 3. If found move all following elements down by one
- * 4. Decrease count of used elements in array
- *
- * This currently doesn't shrink the allocated storage of the array.
+/**
+ * Remove fd from asev
  *
- * @param fdsetp      (rw) pointer to callers pointer to the pollfd array
- * @param polldatap   (rw) pointer to callers pointer to the polldata array
- * @param fdset_usedp (rw) pointer to an int with the number of used elements
- * @param fdset_sizep (rw) pointer to an int which stores the array sizes
- * @param fd          (r)  file descriptor to remove from the arrays
- */
-void fdset_del_fd(struct pollfd **fdsetp,
-                  struct polldata **polldatap,
-                  int *fdset_usedp,
-                  int *fdset_sizep _U_,
-                  int fd)
+ * @returns true if the fd was deleted, otherwise false
+ **/
+bool asev_del_fd(struct asev *asev, int fd)
 {
-    struct pollfd *fdset = *fdsetp;
-    struct polldata *polldata = *polldatap;
-
-    if (*fdset_usedp < 1)
-        return;
-
-    for (int i = 0; i < *fdset_usedp; i++) {
-        if (fdset[i].fd == fd) { /* 1 */
-            if ((i + 1) == *fdset_usedp) { /* 2a */
-                fdset[i].fd = -1;
-                memset(&polldata[i], 0, sizeof(struct polldata));
-            } else if (i < (*fdset_usedp - 1)) { /* 2b */
-                memmove(&fdset[i],
-                        &fdset[i+1],
-                        (*fdset_usedp - i - 1) * sizeof(struct pollfd)); /* 3 */
-                memmove(&polldata[i],
-                        &polldata[i+1],
-                        (*fdset_usedp - i - 1) * sizeof(struct polldata)); /* 3 */
+    int i;
+    int numafter;
+
+    if (asev == NULL) {
+        return false;
+    }
+
+    if (asev->used == 0) {
+        LOG(log_error, logtype_cnid, "asev_del_fd: empty");
+        return false;
+    }
+
+    for (i = 0; i < asev->used; i++) {
+        /*
+         * Scan the array for a matching fd
+         */
+        if (asev->fdset[i].fd == fd) {
+            /*
+             * found fd
+             */
+            if ((i + 1) == asev->used) {
+                /*
+                 * it's the last (or only) array element, simply null it
+                 */
+                asev->fdset[i].fd = -1;
+                asev->data[i].fdtype = 0;
+                asev->data[i].private = NULL;
+            } else {
+                /*
+                 * Move down by one all subsequent elements
+                 */
+                numafter = asev->used - (i + 1);
+                memmove(&asev->fdset[i], &asev->fdset[i+1],
+                        numafter * sizeof(struct pollfd));
+                memmove(&asev->data[i], &asev->data[i+1],
+                        numafter * sizeof(struct asev_data));
             }
-            (*fdset_usedp)--;
-            break;
+            asev->used--;
+            return true;
         }
     }
+
+    return false;
 }
 
 /* Length of the space taken up by a padded control message of length len */