struct GNUNET_NETWORK_Handle
{
+#ifndef MINGW
int fd;
+
+#else
+ SOCKET fd;
+#endif
+
+ /**
+ * Address family / domain.
+ */
+ int af;
};
{
/**
- * Maximum number of any socket socket descriptor in the set
+ * Maximum number of any socket socket descriptor in the set (plus one)
*/
int nsds;
#ifdef WINDOWS
/**
- * Linked list of handles
+ * Linked list of handles
*/
struct GNUNET_CONTAINER_SList *handles;
#endif
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
static void
socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
{
+#ifndef WINDOWS
int value = 1;
- if (0 !=
- setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
+ if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
+#else
+ const char * value = "1";
+ if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, value, sizeof (value)))
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
+#endif
}
socklen_t * address_len)
{
struct GNUNET_NETWORK_Handle *ret;
+
ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
+ ret->af = address->sa_family;
+ /* NOTE: if sa_family does not exist on some platform,
+ using AF_UNSPEC should be safe */
ret->fd = accept (desc->fd, address, address_len);
if (ret->fd == INVALID_SOCKET)
{
#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;
}
socklen_t address_len)
{
int ret;
-
+
+#ifdef IPV6_V6ONLY
+#ifdef IPPROTO_IPV6
+ const int on = 1;
+ if (desc->af == AF_INET6)
+ setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on));
+#if 0
+ /* is this needed or desired? or done elsewhere? */
+ setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on));
+#endif
+#endif
+#endif
ret = bind (desc->fd, address, address_len);
#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;
}
GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
{
int ret;
- int eno;
#ifdef MINGW
ret = closesocket (desc->fd);
#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;
+ ret->af = AF_UNSPEC;
+ return ret;
+#endif
+}
+
+
/**
* Connect a socket
* @param desc socket
* Returns GNUNET_NO if no data is available, or on error!
* @param desc socket
*/
-unsigned int
-GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle * desc)
+ssize_t
+GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle
+ *desc)
{
int error;
- unsigned int pending;
/* How much is there to be read? */
- error = ioctl(desc->fd, FIONREAD, &pending);
- GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
- ("pending is %u bytes, error is %d\n"), pending, error);
-
+#ifndef WINDOWS
+ int pending;
+ error = ioctl (desc->fd, FIONREAD, &pending);
if (error == 0)
+#else
+ u_long pending;
+ error = ioctlsocket (desc->fd, FIONREAD, &pending);
+ if (error != SOCKET_ERROR)
+#endif
return pending;
else
return GNUNET_NO;
ssize_t
GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
void *buffer, size_t length,
- struct sockaddr *src_addr, socklen_t *addrlen)
+ struct sockaddr * src_addr,
+ socklen_t * addrlen)
{
int ret;
int flags;
#ifdef MSG_DONTWAIT
flags |= MSG_DONTWAIT;
-#endif /* */
+#endif
ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
-
#ifdef MINGW
if (SOCKET_ERROR == ret)
SetErrnoFromWinsockError (WSAGetLastError ());
-
-#endif /* */
+#endif
return ret;
}
#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;
}
{
struct GNUNET_NETWORK_Handle *ret;
ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
+ ret->af = domain;
ret->fd = socket (domain, type, protocol);
if (INVALID_SOCKET == ret->fd)
{
#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;
}
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
GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
const struct GNUNET_DISK_FileHandle *h)
{
-
#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;
return GNUNET_YES;
#ifdef MINGW
{
- 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;
+ struct GNUNET_CONTAINER_SList_Iterator *it;
- 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 = (HANDLE *) GNUNET_CONTAINER_slist_get ((const struct GNUNET_CONTAINER_SList_Iterator *)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;
GNUNET_break (0);
}
#ifndef MINGW
- return select (nfds + 1,
+ return select (nfds,
(rfds != NULL) ? &rfds->sds : NULL,
(wfds != NULL) ? &wfds->sds : NULL,
(efds != NULL) ? &efds->sds : NULL,
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;
{
GNUNET_CONTAINER_slist_add (handles_read,
- GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &h,
- sizeof (HANDLE));
+ GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+ &h, sizeof (HANDLE));
retcode++;
}
}
{
GNUNET_CONTAINER_slist_add (handles_except,
- GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &h,
- sizeof (HANDLE));
+ GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+ &h, sizeof (HANDLE));
retcode++;
}
}
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);
GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
}
if (efds)
-
{
GNUNET_NETWORK_fdset_zero (efds);
GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);