X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fnetwork.c;h=08121928db6ee69312b571f4c48878ab68aeebeb;hb=8dfd7bda2f139e2dac27e804167eedc3d227453e;hp=a054709d9959d5693b7e7079e7a5d8eb5ada6582;hpb=5de4d2e77f907cb3d2d734fe1d7eafa943b1d001;p=oweals%2Fgnunet.git diff --git a/src/util/network.c b/src/util/network.c index a054709d9..08121928d 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -40,9 +40,15 @@ struct GNUNET_NETWORK_Handle { #ifndef MINGW int fd; + #else SOCKET fd; #endif + + /** + * Address family / domain. + */ + int af; }; @@ -50,7 +56,7 @@ struct GNUNET_NETWORK_FDSet { /** - * Maximum number of any socket socket descriptor in the set + * Maximum number of any socket socket descriptor in the set (plus one) */ int nsds; @@ -132,11 +138,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 @@ -150,9 +161,9 @@ socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h) static void socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h) { - int value = 1; + int abs_value = 1; if (0 != - setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof (value))) + setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &abs_value, sizeof (abs_value))) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); } #endif @@ -168,10 +179,15 @@ socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h) 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 * abs_value = "1"; + if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value, sizeof (abs_value))) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); +#endif } @@ -189,8 +205,10 @@ 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); + ret->af = address->sa_family; if (ret->fd == INVALID_SOCKET) { #ifdef MINGW @@ -247,11 +265,35 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc, socklen_t address_len) { int ret; - + +#ifdef IPV6_V6ONLY +#ifdef IPPROTO_IPV6 + const int on = 1; + if (desc->af == AF_INET6) + if (0 != setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on))) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt"); +#if 0 + /* is this needed or desired? or done elsewhere? */ + if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt"); +#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; } @@ -278,6 +320,30 @@ GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc) } +/** + * 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 @@ -369,13 +435,14 @@ GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *desc) { int error; - int pending; /* How much is there to be read? */ #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 @@ -554,6 +621,7 @@ GNUNET_NETWORK_socket_create (int domain, int type, int protocol) { 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) { @@ -742,6 +810,23 @@ void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, } +/** + * 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 @@ -751,13 +836,10 @@ void 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)); + h, sizeof (struct GNUNET_DISK_FileHandle)); #else int fd; @@ -782,8 +864,8 @@ GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds, { #ifdef MINGW - return GNUNET_CONTAINER_slist_contains (fds->handles, &h->h, - sizeof (HANDLE)); + return GNUNET_CONTAINER_slist_contains (fds->handles, h, + sizeof (struct GNUNET_DISK_FileHandle)); #else return FD_ISSET (h->fd, &fds->sds); #endif @@ -800,33 +882,48 @@ int GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1, const struct GNUNET_NETWORK_FDSet *fds2) { +#ifndef MINGW int nfds; + nfds = fds1->nsds; - if (nfds < fds2->nsds) + if (nfds > fds2->nsds) nfds = fds2->nsds; - for (; nfds >= 0; nfds--) - if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds)) - return GNUNET_YES; -#ifdef MINGW - { - struct GNUNET_CONTAINER_SList_Iterator *it; + while (nfds > 0) + { + nfds--; + if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds)) + return GNUNET_YES; + } +#else + struct GNUNET_CONTAINER_SList_Iterator *it; + struct GNUNET_DISK_FileHandle *h; + int i; + int j; - 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); + /*This code is somewhat hacky, we are not supposed to know what's + inside of fd_set; also the O(n^2) is really bad... */ + + for (i = 0; i < fds1->sds.fd_count; i++) + { + for (j = 0; j < fds2->sds.fd_count; j++) + { + if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j]) + return GNUNET_YES; + } } + it = GNUNET_CONTAINER_slist_begin (fds1->handles); + while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES) + { + h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL); + if (GNUNET_CONTAINER_slist_contains + (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle))) + { + GNUNET_CONTAINER_slist_iter_destroy (it); + return GNUNET_YES; + } + GNUNET_CONTAINER_slist_next (it); + } + GNUNET_CONTAINER_slist_iter_destroy (it); #endif return GNUNET_NO; } @@ -907,10 +1004,10 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, } struct timeval tv; - tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value; + tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value; tv.tv_usec = - 1000 * (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value)); - if ((nfds == 0) && (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value) + 1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value)); + if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) #ifdef MINGW && handles == 0 #endif @@ -923,11 +1020,11 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, 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, - (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value) + (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv); #else @@ -945,11 +1042,11 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) /* calculate how long we need to wait in milliseconds */ - if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value) + if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ms_total = INFINITE; else - ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value; + ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value; /* select() may be used as a portable way to sleep */ if (!(rfds || wfds || efds)) @@ -1023,28 +1120,38 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, GNUNET_CONTAINER_slist_next (i)) { - HANDLE h; + struct GNUNET_DISK_FileHandle *fh; DWORD dwBytes; - h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL); - if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL)) + fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); + if (fh->type == GNUNET_PIPE) { - retcode = -1; - SetErrnoFromWinError (GetLastError ()); + if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) + { + retcode = -1; + SetErrnoFromWinError (GetLastError ()); -#if DEBUG_NETWORK - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "PeekNamedPipe"); + #if DEBUG_NETWORK + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "PeekNamedPipe"); -#endif - goto select_loop_end; - } - else if (dwBytes) + #endif + goto select_loop_end; + } + else if (dwBytes) + { + GNUNET_CONTAINER_slist_add (handles_read, + GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + } + } + else { + /* Should we wait for more bytes to read here (in case of previous EOF)? */ GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, - &h, sizeof (HANDLE)); - retcode++; + fh, sizeof (struct GNUNET_DISK_FileHandle)); } } GNUNET_CONTAINER_slist_iter_destroy (i); @@ -1060,16 +1167,20 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, GNUNET_CONTAINER_slist_next (i)) { - HANDLE h; + struct GNUNET_DISK_FileHandle *fh; DWORD dwBytes; - h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL); - if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL)) + fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); + if (fh->type == GNUNET_PIPE) { - GNUNET_CONTAINER_slist_add (handles_except, - GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, - &h, sizeof (HANDLE)); - retcode++; + if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) + + { + GNUNET_CONTAINER_slist_add (handles_except, + GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + } } } GNUNET_CONTAINER_slist_iter_destroy (i); @@ -1117,19 +1228,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); @@ -1137,7 +1244,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);