trying to port statvfs call to BSD
[oweals/gnunet.git] / src / util / network.c
index d889fa94bde1cb022464cd8ef9a1ad3a986d409f..101e794d07c892827182455620e7d30dec5f2b88 100644 (file)
 
 struct GNUNET_NETWORK_Handle
 {
+#ifndef MINGW
   int fd;
+
+#else
+  SOCKET fd;
+#endif
+
 };
 
 
@@ -57,7 +63,7 @@ struct GNUNET_NETWORK_FDSet
 
 #ifdef WINDOWS
   /**
-   * Linked list of handles 
+   * Linked list of handles
    */
   struct GNUNET_CONTAINER_SList *handles;
 #endif
@@ -128,11 +134,16 @@ static int
 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
 {
   int i;
-  i = fcntl (h->fd, F_GETFD);
+
+  i = fcntl (h->fd, F_GETFD);  
+  if (i < 0)
+    return GNUNET_SYSERR;
   if (i == (i | FD_CLOEXEC))
     return GNUNET_OK;
-  return (fcntl (h->fd, F_SETFD, i | FD_CLOEXEC) == 0)
-    ? GNUNET_OK : GNUNET_SYSERR;
+  i |= FD_CLOEXEC;
+  if (fcntl (h->fd, F_SETFD, i) < 0)
+    return GNUNET_SYSERR;
+  return GNUNET_OK;
 }
 #endif
 
@@ -185,6 +196,7 @@ GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
                               socklen_t * address_len)
 {
   struct GNUNET_NETWORK_Handle *ret;
+
   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
   ret->fd = accept (desc->fd, address, address_len);
   if (ret->fd == INVALID_SOCKET)
@@ -222,7 +234,10 @@ GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
 #ifdef DARWIN
   socket_set_nosigpipe (ret);
 #endif
-  socket_set_nodelay (ret);
+#ifdef AF_UNIX
+  if (address->sa_family != AF_UNIX)
+#endif
+    socket_set_nodelay (ret);
   return ret;
 }
 
@@ -245,6 +260,17 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
 #ifdef MINGW
   if (SOCKET_ERROR == ret)
     SetErrnoFromWinsockError (WSAGetLastError ());
+#else
+#ifndef LINUX
+  if ( (ret == 0) && (address->sa_family == AF_UNIX))
+    {
+      const struct sockaddr_un *un = (const struct sockaddr_un*) address;
+      if (0 != unlink (un->sun_path))
+       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+                                 "unlink",
+                                 un->sun_path);
+    }
+#endif
 #endif
   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
 }
@@ -259,7 +285,6 @@ int
 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
 {
   int ret;
-  int eno;
 
 #ifdef MINGW
   ret = closesocket (desc->fd);
@@ -267,13 +292,34 @@ GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
 #else
   ret = close (desc->fd);
 #endif
-  eno = errno;
   GNUNET_free (desc);
-  errno = eno;
   return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
 }
 
 
+/**
+ * Box a native socket (and check that it is a socket).
+ *
+ * @param fd socket to box
+ * @return NULL on error (including not supported on target platform)
+ */
+struct GNUNET_NETWORK_Handle *
+GNUNET_NETWORK_socket_box_native (int fd)
+{
+#if MINGW
+  return NULL;
+#else
+  struct GNUNET_NETWORK_Handle *ret;
+
+  if (fcntl (fd, F_GETFD) < 0)
+    return NULL; /* invalid FD */
+  ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle)); 
+  ret->fd = fd;
+  return ret;
+#endif
+}
+
+
 /**
  * Connect a socket
  * @param desc socket
@@ -354,6 +400,64 @@ GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
 }
 
 
+/**
+ * How much data is available to be read on this descriptor?
+ *
+ * Returns GNUNET_NO if no data is available, or on error!
+ * @param desc socket
+ */
+ssize_t
+GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle
+                                       *desc)
+{
+  int error;
+  int pending;
+
+  /* How much is there to be read? */
+#ifndef WINDOWS
+  error = ioctl (desc->fd, FIONREAD, &pending);
+  if (error == 0)
+#else
+  error = ioctlsocket (desc->fd, FIONREAD, &pending);
+  if (error != SOCKET_ERROR)
+#endif
+    return pending;
+  else
+    return GNUNET_NO;
+}
+
+/**
+ * Read data from a connected socket (always non-blocking).
+ * @param desc socket
+ * @param buffer buffer
+ * @param length length of buffer
+ * @param src_addr either the source to recv from, or all zeroes
+ *        to be filled in by recvfrom
+ * @param addrlen length of the addr
+ */
+ssize_t
+GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
+                                void *buffer, size_t length,
+                                struct sockaddr * src_addr,
+                                socklen_t * addrlen)
+{
+  int ret;
+  int flags;
+  flags = 0;
+
+#ifdef MSG_DONTWAIT
+  flags |= MSG_DONTWAIT;
+
+#endif
+  ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
+#ifdef MINGW
+  if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif 
+  return ret;
+}
+
+
 /**
  * Read data from a connected socket (always non-blocking).
  * @param desc socket
@@ -370,15 +474,12 @@ GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
 
 #ifdef MSG_DONTWAIT
   flags |= MSG_DONTWAIT;
-
-#endif /*  */
+#endif
   ret = recv (desc->fd, buffer, length, flags);
-
 #ifdef MINGW
   if (SOCKET_ERROR == ret)
     SetErrnoFromWinsockError (WSAGetLastError ());
-
-#endif /*  */
+#endif
   return ret;
 }
 
@@ -531,7 +632,11 @@ GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
 #ifdef DARWIN
   socket_set_nosigpipe (ret);
 #endif
-  if (type == SOCK_STREAM)
+  if ( (type == SOCK_STREAM) 
+#ifdef AF_UNIX
+       && (domain != AF_UNIX) 
+#endif
+       )
     socket_set_nodelay (ret);
   return ret;
 }
@@ -643,6 +748,12 @@ GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
 #endif
 }
 
+int
+GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
+{
+  return desc->fd;
+}
+
 /**
  * Copy a native fd set
  *
@@ -658,6 +769,38 @@ GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
   to->nsds = nfds;
 }
 
+
+/**
+ * Set a native fd in a set
+ *
+ * @param to destination
+ * @param nfd native FD to set
+ */
+void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to,
+                                     int nfd)
+{
+  FD_SET (nfd, &to->sds);
+  to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
+}
+
+
+/**
+ * Test native fd in a set
+ *
+ * @param to set to test, NULL for empty set
+ * @param nfd native FD to test, or -1 for none
+ * @return GNUNET_YES if FD is set in the set
+ */
+int 
+GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
+                                 int nfd)
+{
+  if ( (nfd == -1) || (to == NULL) )
+    return GNUNET_NO;
+  return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
+}
+
+
 /**
  * Add a file handle to the fd set
  * @param fds fd set
@@ -671,7 +814,9 @@ GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
 #ifdef MINGW
   HANDLE hw;
   GNUNET_DISK_internal_file_handle_ (h, &hw, sizeof (HANDLE));
-  GNUNET_CONTAINER_slist_add (fds->handles, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &hw, sizeof (HANDLE));
+  GNUNET_CONTAINER_slist_add (fds->handles,
+                              GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+                              &hw, sizeof (HANDLE));
 
 #else
   int fd;
@@ -723,20 +868,23 @@ GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
       return GNUNET_YES;
 #ifdef MINGW
   {
-      struct GNUNET_CONTAINER_SList_Iterator *it;
+    struct GNUNET_CONTAINER_SList_Iterator *it;
 
-      for(it = GNUNET_CONTAINER_slist_begin (fds1->handles); GNUNET_CONTAINER_slist_end (it) != GNUNET_YES; GNUNET_CONTAINER_slist_next (it))
-        {
-          HANDLE *h;
-
-          h = GNUNET_CONTAINER_slist_get (it, NULL);
-          if (GNUNET_CONTAINER_slist_contains (fds2->handles, h, sizeof (HANDLE)))
-            {
-              GNUNET_CONTAINER_slist_iter_destroy (it);
-              return GNUNET_YES;
-            }
-        }
-      GNUNET_CONTAINER_slist_iter_destroy (it);
+    for (it = GNUNET_CONTAINER_slist_begin (fds1->handles);
+         GNUNET_CONTAINER_slist_end (it) != GNUNET_YES;
+         GNUNET_CONTAINER_slist_next (it))
+      {
+        HANDLE *h;
+
+        h = GNUNET_CONTAINER_slist_get (it, NULL);
+        if (GNUNET_CONTAINER_slist_contains
+            (fds2->handles, h, sizeof (HANDLE)))
+          {
+            GNUNET_CONTAINER_slist_iter_destroy (it);
+            return GNUNET_YES;
+          }
+      }
+    GNUNET_CONTAINER_slist_iter_destroy (it);
   }
 #endif
   return GNUNET_NO;
@@ -845,7 +993,8 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
   DWORD limit;
   fd_set sock_read, sock_write, sock_except;
   fd_set aread, awrite, aexcept;
-  struct GNUNET_CONTAINER_SList *handles_read, *handles_write, *handles_except;
+  struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
+    *handles_except;
 
   int i;
   struct timeval tvslice;
@@ -952,8 +1101,8 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
 
                 {
                   GNUNET_CONTAINER_slist_add (handles_read,
-                      GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &h,
-                      sizeof (HANDLE));
+                                              GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+                                              &h, sizeof (HANDLE));
                   retcode++;
                 }
             }
@@ -977,8 +1126,8 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
 
                 {
                   GNUNET_CONTAINER_slist_add (handles_except,
-                      GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &h,
-                      sizeof (HANDLE));
+                                              GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+                                              &h, sizeof (HANDLE));
                   retcode++;
                 }
             }
@@ -1027,19 +1176,15 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
 
   if (retcode != -1)
-
     {
       if (rfds)
-
         {
           GNUNET_NETWORK_fdset_zero (rfds);
           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
           GNUNET_CONTAINER_slist_clear (rfds->handles);
           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
-
         }
       if (wfds)
-
         {
           GNUNET_NETWORK_fdset_zero (wfds);
           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
@@ -1047,7 +1192,6 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
         }
       if (efds)
-
         {
           GNUNET_NETWORK_fdset_zero (efds);
           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);