diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-08-01 20:32:59 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-08-01 20:32:59 +0000 |
commit | ff2d2e7ea5f470af1c345e7c66fe320d4c9d2d33 (patch) | |
tree | 4a279a987a23b018ff568099759e87d6e6b09354 /src/util | |
parent | 87f795e4d28eee0ae57f9d916ef12141937e4b4a (diff) | |
download | gnunet-ff2d2e7ea5f470af1c345e7c66fe320d4c9d2d33.tar.gz gnunet-ff2d2e7ea5f470af1c345e7c66fe320d4c9d2d33.zip |
LRN: Bratao's select() implementation for W32
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/disk.c | 217 | ||||
-rw-r--r-- | src/util/disk.h | 10 | ||||
-rw-r--r-- | src/util/network.c | 778 |
3 files changed, 710 insertions, 295 deletions
diff --git a/src/util/disk.c b/src/util/disk.c index 4d2ec8d81..fd8e5a654 100644 --- a/src/util/disk.c +++ b/src/util/disk.c | |||
@@ -36,6 +36,8 @@ | |||
36 | 36 | ||
37 | #define DEBUG_NPIPE GNUNET_NO | 37 | #define DEBUG_NPIPE GNUNET_NO |
38 | 38 | ||
39 | #define DEBUG_PIPE GNUNET_NO | ||
40 | |||
39 | /** | 41 | /** |
40 | * Block size for IO for copying files. | 42 | * Block size for IO for copying files. |
41 | */ | 43 | */ |
@@ -55,6 +57,10 @@ | |||
55 | #include <sys/statvfs.h> | 57 | #include <sys/statvfs.h> |
56 | #else | 58 | #else |
57 | #ifdef MINGW | 59 | #ifdef MINGW |
60 | #ifndef PIPE_BUF | ||
61 | #define PIPE_BUF 512 | ||
62 | ULONG PipeSerialNumber; | ||
63 | #endif | ||
58 | #define _IFMT 0170000 /* type of file */ | 64 | #define _IFMT 0170000 /* type of file */ |
59 | #define _IFLNK 0120000 /* symbolic link */ | 65 | #define _IFLNK 0120000 /* symbolic link */ |
60 | #define S_ISLNK(m) (((m)&_IFMT) == _IFLNK) | 66 | #define S_ISLNK(m) (((m)&_IFMT) == _IFLNK) |
@@ -643,11 +649,26 @@ GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle * h, void *result, | |||
643 | #ifdef MINGW | 649 | #ifdef MINGW |
644 | DWORD bytesRead; | 650 | DWORD bytesRead; |
645 | 651 | ||
646 | if (!ReadFile (h->h, result, len, &bytesRead, NULL)) | 652 | if(h->type != GNUNET_PIPE) |
653 | { | ||
654 | if (!ReadFile (h->h, result, len, &bytesRead, NULL)) | ||
647 | { | 655 | { |
648 | SetErrnoFromWinError (GetLastError ()); | 656 | SetErrnoFromWinError (GetLastError ()); |
649 | return GNUNET_SYSERR; | 657 | return GNUNET_SYSERR; |
650 | } | 658 | } |
659 | } | ||
660 | else | ||
661 | { | ||
662 | if (!ReadFile (h->h, result, len, NULL, h->oOverlapRead)) | ||
663 | { | ||
664 | if(GetLastError () != ERROR_IO_PENDING ) | ||
665 | { | ||
666 | SetErrnoFromWinError (GetLastError ()); | ||
667 | return GNUNET_SYSERR; | ||
668 | } | ||
669 | } | ||
670 | GetOverlappedResult(h->h, h->oOverlapRead, &bytesRead, TRUE); | ||
671 | } | ||
651 | return bytesRead; | 672 | return bytesRead; |
652 | #else | 673 | #else |
653 | return read (h->fd, result, len); | 674 | return read (h->fd, result, len); |
@@ -700,11 +721,35 @@ GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h, | |||
700 | #ifdef MINGW | 721 | #ifdef MINGW |
701 | DWORD bytesWritten; | 722 | DWORD bytesWritten; |
702 | 723 | ||
703 | if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL)) | 724 | if(h->type != GNUNET_PIPE) |
725 | { | ||
726 | if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL)) | ||
704 | { | 727 | { |
705 | SetErrnoFromWinError (GetLastError ()); | 728 | SetErrnoFromWinError (GetLastError ()); |
706 | return GNUNET_SYSERR; | 729 | return GNUNET_SYSERR; |
707 | } | 730 | } |
731 | } | ||
732 | else | ||
733 | { | ||
734 | #if DEBUG_PIPE | ||
735 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "It is a pipe trying to write\n"); | ||
736 | #endif | ||
737 | if (!WriteFile (h->h, buffer, n, NULL, h->oOverlapWrite)) | ||
738 | { | ||
739 | if(GetLastError () != ERROR_IO_PENDING ) | ||
740 | { | ||
741 | SetErrnoFromWinError (GetLastError ()); | ||
742 | #if DEBUG_PIPE | ||
743 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error writing to pipe\n"); | ||
744 | #endif | ||
745 | return GNUNET_SYSERR; | ||
746 | } | ||
747 | } | ||
748 | #if DEBUG_PIPE | ||
749 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will get overlapped result\n"); | ||
750 | #endif | ||
751 | GetOverlappedResult(h->h, h->oOverlapWrite, &bytesWritten, TRUE); | ||
752 | } | ||
708 | return bytesWritten; | 753 | return bytesWritten; |
709 | #else | 754 | #else |
710 | return write (h->fd, buffer, n); | 755 | return write (h->fd, buffer, n); |
@@ -1388,6 +1433,8 @@ GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h) | |||
1388 | { | 1433 | { |
1389 | SetErrnoFromWinError (GetLastError ()); | 1434 | SetErrnoFromWinError (GetLastError ()); |
1390 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "close"); | 1435 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "close"); |
1436 | GNUNET_free (h->oOverlapRead); | ||
1437 | GNUNET_free (h->oOverlapWrite); | ||
1391 | GNUNET_free (h); | 1438 | GNUNET_free (h); |
1392 | return GNUNET_SYSERR; | 1439 | return GNUNET_SYSERR; |
1393 | } | 1440 | } |
@@ -1647,6 +1694,148 @@ GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h) | |||
1647 | #endif | 1694 | #endif |
1648 | } | 1695 | } |
1649 | 1696 | ||
1697 | #if WINDOWS | ||
1698 | /* Copyright Bob Byrnes <byrnes <at> curl.com> | ||
1699 | http://permalink.gmane.org/gmane.os.cygwin.patches/2121 | ||
1700 | */ | ||
1701 | /* Create a pipe, and return handles to the read and write ends, | ||
1702 | just like CreatePipe, but ensure that the write end permits | ||
1703 | FILE_READ_ATTRIBUTES access, on later versions of win32 where | ||
1704 | this is supported. This access is needed by NtQueryInformationFile, | ||
1705 | which is used to implement select and nonblocking writes. | ||
1706 | Note that the return value is either NO_ERROR or GetLastError, | ||
1707 | unlike CreatePipe, which returns a bool for success or failure. */ | ||
1708 | static int | ||
1709 | create_selectable_pipe (PHANDLE read_pipe_ptr, | ||
1710 | PHANDLE write_pipe_ptr, | ||
1711 | LPSECURITY_ATTRIBUTES sa_ptr, | ||
1712 | DWORD psize, | ||
1713 | DWORD dwReadMode, | ||
1714 | DWORD dwWriteMode) | ||
1715 | { | ||
1716 | /* Default to error. */ | ||
1717 | *read_pipe_ptr = *write_pipe_ptr = INVALID_HANDLE_VALUE; | ||
1718 | |||
1719 | HANDLE read_pipe = INVALID_HANDLE_VALUE, write_pipe = INVALID_HANDLE_VALUE; | ||
1720 | |||
1721 | /* Ensure that there is enough pipe buffer space for atomic writes. */ | ||
1722 | if (psize < PIPE_BUF) | ||
1723 | psize = PIPE_BUF; | ||
1724 | |||
1725 | char pipename[MAX_PATH]; | ||
1726 | |||
1727 | /* Retry CreateNamedPipe as long as the pipe name is in use. | ||
1728 | Retrying will probably never be necessary, but we want | ||
1729 | to be as robust as possible. */ | ||
1730 | while (1) | ||
1731 | { | ||
1732 | static volatile LONG pipe_unique_id; | ||
1733 | |||
1734 | snprintf (pipename, sizeof pipename, "\\\\.\\pipe\\gnunet-%d-%ld", | ||
1735 | getpid (), InterlockedIncrement ((LONG *)&pipe_unique_id)); | ||
1736 | #if DEBUG_PIPE | ||
1737 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CreateNamedPipe: name = %s, size = %lu\n", pipename, psize); | ||
1738 | #endif | ||
1739 | /* Use CreateNamedPipe instead of CreatePipe, because the latter | ||
1740 | returns a write handle that does not permit FILE_READ_ATTRIBUTES | ||
1741 | access, on versions of win32 earlier than WinXP SP2. | ||
1742 | CreatePipe also stupidly creates a full duplex pipe, which is | ||
1743 | a waste, since only a single direction is actually used. | ||
1744 | It's important to only allow a single instance, to ensure that | ||
1745 | the pipe was not created earlier by some other process, even if | ||
1746 | the pid has been reused. We avoid FILE_FLAG_FIRST_PIPE_INSTANCE | ||
1747 | because that is only available for Win2k SP2 and WinXP. */ | ||
1748 | read_pipe = CreateNamedPipeA (pipename, | ||
1749 | PIPE_ACCESS_INBOUND | dwReadMode, | ||
1750 | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, | ||
1751 | 1, /* max instances */ | ||
1752 | psize, /* output buffer size */ | ||
1753 | psize, /* input buffer size */ | ||
1754 | NMPWAIT_USE_DEFAULT_WAIT, | ||
1755 | sa_ptr); | ||
1756 | |||
1757 | if (read_pipe != INVALID_HANDLE_VALUE) | ||
1758 | { | ||
1759 | #if DEBUG_PIPE | ||
1760 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pipe read handle = %p\n", read_pipe); | ||
1761 | #endif | ||
1762 | break; | ||
1763 | } | ||
1764 | |||
1765 | DWORD err = GetLastError (); | ||
1766 | switch (err) | ||
1767 | { | ||
1768 | case ERROR_PIPE_BUSY: | ||
1769 | /* The pipe is already open with compatible parameters. | ||
1770 | Pick a new name and retry. */ | ||
1771 | #if DEBUG_PIPE | ||
1772 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pipe busy, retrying\n"); | ||
1773 | #endif | ||
1774 | continue; | ||
1775 | case ERROR_ACCESS_DENIED: | ||
1776 | /* The pipe is already open with incompatible parameters. | ||
1777 | Pick a new name and retry. */ | ||
1778 | #if DEBUG_PIPE | ||
1779 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pipe access denied, retrying\n"); | ||
1780 | #endif | ||
1781 | continue; | ||
1782 | case ERROR_CALL_NOT_IMPLEMENTED: | ||
1783 | /* We are on an older Win9x platform without named pipes. | ||
1784 | Return an anonymous pipe as the best approximation. */ | ||
1785 | #if DEBUG_PIPE | ||
1786 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CreateNamedPipe not implemented, resorting to " | ||
1787 | "CreatePipe: size = %lu\n", psize); | ||
1788 | #endif | ||
1789 | if (CreatePipe (read_pipe_ptr, write_pipe_ptr, sa_ptr, psize)) | ||
1790 | { | ||
1791 | #if DEBUG_PIPE | ||
1792 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pipe read handle = %p\n", *read_pipe_ptr); | ||
1793 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pipe write handle = %p\n", *write_pipe_ptr); | ||
1794 | #endif | ||
1795 | return GNUNET_OK; | ||
1796 | } | ||
1797 | err = GetLastError (); | ||
1798 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "CreatePipe failed: %d\n", err); | ||
1799 | return err; | ||
1800 | default: | ||
1801 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "CreateNamedPipe failed: %d\n", err); | ||
1802 | return err; | ||
1803 | } | ||
1804 | /* NOTREACHED */ | ||
1805 | } | ||
1806 | #if DEBUG_PIPE | ||
1807 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CreateFile: name = %s\n", pipename); | ||
1808 | #endif | ||
1809 | |||
1810 | /* Open the named pipe for writing. | ||
1811 | Be sure to permit FILE_READ_ATTRIBUTES access. */ | ||
1812 | write_pipe = CreateFileA (pipename, | ||
1813 | GENERIC_WRITE | FILE_READ_ATTRIBUTES, | ||
1814 | 0, /* share mode */ | ||
1815 | sa_ptr, | ||
1816 | OPEN_EXISTING, | ||
1817 | dwWriteMode, /* flags and attributes */ | ||
1818 | 0); /* handle to template file */ | ||
1819 | |||
1820 | if (write_pipe == INVALID_HANDLE_VALUE) | ||
1821 | { | ||
1822 | /* Failure. */ | ||
1823 | DWORD err = GetLastError (); | ||
1824 | #if DEBUG_PIPE | ||
1825 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CreateFile failed: %d\n", err); | ||
1826 | #endif | ||
1827 | CloseHandle (read_pipe); | ||
1828 | return err; | ||
1829 | } | ||
1830 | #if DEBUG_PIPE | ||
1831 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pipe write handle = %p\n", write_pipe); | ||
1832 | #endif | ||
1833 | /* Success. */ | ||
1834 | *read_pipe_ptr = read_pipe; | ||
1835 | *write_pipe_ptr = write_pipe; | ||
1836 | return GNUNET_OK; | ||
1837 | } | ||
1838 | #endif | ||
1650 | 1839 | ||
1651 | /** | 1840 | /** |
1652 | * Creates an interprocess channel | 1841 | * Creates an interprocess channel |
@@ -1720,7 +1909,7 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write) | |||
1720 | BOOL ret; | 1909 | BOOL ret; |
1721 | HANDLE tmp_handle; | 1910 | HANDLE tmp_handle; |
1722 | 1911 | ||
1723 | ret = CreatePipe (&p->fd[0]->h, &p->fd[1]->h, NULL, 0); | 1912 | ret = create_selectable_pipe (&p->fd[0]->h, &p->fd[1]->h, NULL, 0, FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED); |
1724 | if (!ret) | 1913 | if (!ret) |
1725 | { | 1914 | { |
1726 | GNUNET_free (p); | 1915 | GNUNET_free (p); |
@@ -1763,6 +1952,18 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write) | |||
1763 | } | 1952 | } |
1764 | p->fd[0]->type = GNUNET_PIPE; | 1953 | p->fd[0]->type = GNUNET_PIPE; |
1765 | p->fd[1]->type = GNUNET_PIPE; | 1954 | p->fd[1]->type = GNUNET_PIPE; |
1955 | |||
1956 | p->fd[0]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
1957 | p->fd[0]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
1958 | p->fd[1]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
1959 | p->fd[1]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
1960 | |||
1961 | p->fd[0]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
1962 | p->fd[0]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
1963 | |||
1964 | p->fd[1]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
1965 | p->fd[1]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
1966 | |||
1766 | #endif | 1967 | #endif |
1767 | return p; | 1968 | return p; |
1768 | } | 1969 | } |
@@ -1965,6 +2166,12 @@ GNUNET_DISK_npipe_create (char **fn, | |||
1965 | ret->h = h; | 2166 | ret->h = h; |
1966 | ret->type = GNUNET_PIPE; | 2167 | ret->type = GNUNET_PIPE; |
1967 | 2168 | ||
2169 | ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
2170 | ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
2171 | |||
2172 | ret->oOverlapRead->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | ||
2173 | ret->oOverlapWrite->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | ||
2174 | |||
1968 | return ret; | 2175 | return ret; |
1969 | #else | 2176 | #else |
1970 | if (*fn == NULL) | 2177 | if (*fn == NULL) |
@@ -2029,6 +2236,10 @@ GNUNET_DISK_npipe_open (const char *fn, | |||
2029 | ret = GNUNET_malloc(sizeof(*ret)); | 2236 | ret = GNUNET_malloc(sizeof(*ret)); |
2030 | ret->h = h; | 2237 | ret->h = h; |
2031 | ret->type = GNUNET_PIPE; | 2238 | ret->type = GNUNET_PIPE; |
2239 | ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
2240 | ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
2241 | ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
2242 | ret->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
2032 | 2243 | ||
2033 | return ret; | 2244 | return ret; |
2034 | #else | 2245 | #else |
diff --git a/src/util/disk.h b/src/util/disk.h index 093d70492..793b8219f 100644 --- a/src/util/disk.h +++ b/src/util/disk.h | |||
@@ -45,6 +45,16 @@ struct GNUNET_DISK_FileHandle | |||
45 | * Type | 45 | * Type |
46 | */ | 46 | */ |
47 | enum {GNUNET_DISK_FILE, GNUNET_PIPE} type; | 47 | enum {GNUNET_DISK_FILE, GNUNET_PIPE} type; |
48 | |||
49 | /** | ||
50 | * Structure for overlapped reading (for pipes) | ||
51 | */ | ||
52 | OVERLAPPED *oOverlapRead; | ||
53 | |||
54 | /** | ||
55 | * Structure for overlapped writing (for pipes) | ||
56 | */ | ||
57 | OVERLAPPED *oOverlapWrite; | ||
48 | #else | 58 | #else |
49 | 59 | ||
50 | /** | 60 | /** |
diff --git a/src/util/network.c b/src/util/network.c index 6a7453510..9c6d0c90b 100644 --- a/src/util/network.c +++ b/src/util/network.c | |||
@@ -220,6 +220,17 @@ GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc, | |||
220 | struct GNUNET_NETWORK_Handle *ret; | 220 | struct GNUNET_NETWORK_Handle *ret; |
221 | 221 | ||
222 | ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle)); | 222 | ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle)); |
223 | #if DEBUG_NETWORK | ||
224 | { | ||
225 | struct sockaddr name; | ||
226 | int namelen = sizeof (name); | ||
227 | int gsn = getsockname (desc->fd, &name, &namelen); | ||
228 | if (gsn == 0) | ||
229 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
230 | "Accepting connection on `%s'\n", | ||
231 | GNUNET_a2s (&name, namelen)); | ||
232 | } | ||
233 | #endif | ||
223 | ret->fd = accept (desc->fd, address, address_len); | 234 | ret->fd = accept (desc->fd, address, address_len); |
224 | if (address != NULL) | 235 | if (address != NULL) |
225 | ret->af = address->sa_family; | 236 | ret->af = address->sa_family; |
@@ -333,8 +344,17 @@ GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc) | |||
333 | int ret; | 344 | int ret; |
334 | 345 | ||
335 | #ifdef MINGW | 346 | #ifdef MINGW |
347 | DWORD error = 0; | ||
348 | #if DEBUG_NETWORK | ||
349 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_NETWORK_socket_close", "Closing 0x%x\n", desc->fd); | ||
350 | #endif | ||
351 | SetLastError (0); | ||
336 | ret = closesocket (desc->fd); | 352 | ret = closesocket (desc->fd); |
337 | SetErrnoFromWinsockError (WSAGetLastError ()); | 353 | error = WSAGetLastError (); |
354 | SetErrnoFromWinsockError (error); | ||
355 | #if DEBUG_NETWORK | ||
356 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_NETWORK_socket_close", "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret, error); | ||
357 | #endif | ||
338 | #else | 358 | #else |
339 | ret = close (desc->fd); | 359 | ret = close (desc->fd); |
340 | #endif | 360 | #endif |
@@ -350,7 +370,7 @@ GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc) | |||
350 | } | 370 | } |
351 | #endif | 371 | #endif |
352 | #endif | 372 | #endif |
353 | GNUNET_free_non_null (desc->addr); | 373 | GNUNET_free_non_null (desc->addr); |
354 | GNUNET_free (desc); | 374 | GNUNET_free (desc); |
355 | return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR; | 375 | return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR; |
356 | } | 376 | } |
@@ -431,7 +451,6 @@ GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc, | |||
431 | 451 | ||
432 | else if (SOCKET_ERROR == ret) | 452 | else if (SOCKET_ERROR == ret) |
433 | SetErrnoFromWinsockError (WSAGetLastError ()); | 453 | SetErrnoFromWinsockError (WSAGetLastError ()); |
434 | |||
435 | #endif | 454 | #endif |
436 | return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; | 455 | return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; |
437 | } | 456 | } |
@@ -739,11 +758,17 @@ GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc) | |||
739 | { | 758 | { |
740 | int value = 0; | 759 | int value = 0; |
741 | int ret = 0; | 760 | int ret = 0; |
742 | 761 | #if WINDOWS | |
762 | if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value, sizeof (value)))) | ||
763 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); | ||
764 | if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value, sizeof (value)))) | ||
765 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); | ||
766 | #else | ||
743 | if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value)))) | 767 | if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value)))) |
744 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); | 768 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); |
745 | if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value)))) | 769 | if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value)))) |
746 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); | 770 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); |
771 | #endif | ||
747 | 772 | ||
748 | return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; | 773 | return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; |
749 | } | 774 | } |
@@ -984,10 +1009,27 @@ GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1, | |||
984 | it = GNUNET_CONTAINER_slist_begin (fds1->handles); | 1009 | it = GNUNET_CONTAINER_slist_begin (fds1->handles); |
985 | while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES) | 1010 | while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES) |
986 | { | 1011 | { |
1012 | #if DEBUG_NETWORK | ||
1013 | struct GNUNET_CONTAINER_SList_Iterator *t; | ||
1014 | #endif | ||
987 | h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL); | 1015 | h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL); |
1016 | #if DEBUG_NETWORK | ||
1017 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n", h->h); | ||
1018 | for (t = GNUNET_CONTAINER_slist_begin (fds2->handles); | ||
1019 | GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; | ||
1020 | GNUNET_CONTAINER_slist_next (t)) | ||
1021 | { | ||
1022 | struct GNUNET_DISK_FileHandle *fh; | ||
1023 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL); | ||
1024 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h); | ||
1025 | } | ||
1026 | #endif | ||
988 | if (GNUNET_CONTAINER_slist_contains | 1027 | if (GNUNET_CONTAINER_slist_contains |
989 | (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle))) | 1028 | (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle))) |
990 | { | 1029 | { |
1030 | #if DEBUG_NETWORK | ||
1031 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Match!\n"); | ||
1032 | #endif | ||
991 | GNUNET_CONTAINER_slist_iter_destroy (it); | 1033 | GNUNET_CONTAINER_slist_iter_destroy (it); |
992 | return GNUNET_YES; | 1034 | return GNUNET_YES; |
993 | } | 1035 | } |
@@ -1043,40 +1085,80 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, | |||
1043 | struct GNUNET_NETWORK_FDSet *efds, | 1085 | struct GNUNET_NETWORK_FDSet *efds, |
1044 | const struct GNUNET_TIME_Relative timeout) | 1086 | const struct GNUNET_TIME_Relative timeout) |
1045 | { | 1087 | { |
1046 | int nfds; | 1088 | int nfds = 0; |
1047 | #ifdef MINGW | 1089 | #ifdef MINGW |
1048 | int handles; | 1090 | int handles = 0; |
1091 | int ex_handles = 0; | ||
1092 | int read_handles = 0; | ||
1093 | int write_handles = 0; | ||
1094 | |||
1095 | int i = 0; | ||
1096 | int retcode = 0; | ||
1097 | DWORD ms_total = 0; | ||
1098 | |||
1099 | int nsock = 0, nhandles = 0, nSockEvents = 0; | ||
1100 | |||
1101 | static HANDLE hEventRead = 0; | ||
1102 | static HANDLE hEventWrite = 0; | ||
1103 | static HANDLE hEventException = 0; | ||
1104 | static HANDLE hEventPipeWrite = 0; | ||
1105 | static HANDLE hEventReadReady = 0; | ||
1106 | |||
1107 | int readPipes = 0; | ||
1108 | int writePipePos = 0; | ||
1109 | |||
1110 | HANDLE handle_array[FD_SETSIZE + 2]; | ||
1111 | int returncode = -1; | ||
1112 | DWORD newretcode = 0; | ||
1113 | int returnedpos = 0; | ||
1114 | |||
1115 | struct GNUNET_CONTAINER_SList *handles_read, *handles_write, *handles_except; | ||
1116 | |||
1117 | fd_set aread, awrite, aexcept; | ||
1118 | #if DEBUG_NETWORK | ||
1119 | fd_set bread, bwrite, bexcept; | ||
1049 | #endif | 1120 | #endif |
1050 | nfds = 0; | 1121 | |
1051 | #ifdef MINGW | 1122 | /* TODO: Make this growable */ |
1052 | handles = 0; | 1123 | struct GNUNET_DISK_FileHandle *readArray[50]; |
1124 | #else | ||
1125 | struct timeval tv; | ||
1053 | #endif | 1126 | #endif |
1054 | if (NULL != rfds) | 1127 | if (NULL != rfds) |
1055 | { | 1128 | { |
1056 | nfds = rfds->nsds; | 1129 | nfds = rfds->nsds; |
1057 | #ifdef MINGW | 1130 | #ifdef MINGW |
1058 | handles = GNUNET_CONTAINER_slist_count (rfds->handles); | 1131 | handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles); |
1132 | #if DEBUG_NETWORK | ||
1133 | { | ||
1134 | struct GNUNET_CONTAINER_SList_Iterator *t; | ||
1135 | for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); | ||
1136 | GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; | ||
1137 | GNUNET_CONTAINER_slist_next (t)) | ||
1138 | { | ||
1139 | struct GNUNET_DISK_FileHandle *fh; | ||
1140 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL); | ||
1141 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h, fh); | ||
1142 | } | ||
1143 | } | ||
1144 | #endif | ||
1059 | #endif | 1145 | #endif |
1060 | } | 1146 | } |
1061 | if (NULL != wfds) | 1147 | if (NULL != wfds) |
1062 | { | 1148 | { |
1063 | nfds = GNUNET_MAX (nfds, wfds->nsds); | 1149 | nfds = GNUNET_MAX (nfds, wfds->nsds); |
1064 | #ifdef MINGW | 1150 | #ifdef MINGW |
1065 | handles += GNUNET_CONTAINER_slist_count (wfds->handles); | 1151 | handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles); |
1066 | #endif | 1152 | #endif |
1067 | } | 1153 | } |
1068 | if (NULL != efds) | 1154 | if (NULL != efds) |
1069 | { | 1155 | { |
1070 | nfds = GNUNET_MAX (nfds, efds->nsds); | 1156 | nfds = GNUNET_MAX (nfds, efds->nsds); |
1071 | #ifdef MINGW | 1157 | #ifdef MINGW |
1072 | handles += GNUNET_CONTAINER_slist_count (efds->handles); | 1158 | handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles); |
1073 | #endif | 1159 | #endif |
1074 | } | 1160 | } |
1075 | 1161 | ||
1076 | struct timeval tv; | ||
1077 | tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value; | ||
1078 | tv.tv_usec = | ||
1079 | 1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value)); | ||
1080 | if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) | 1162 | if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) |
1081 | #ifdef MINGW | 1163 | #ifdef MINGW |
1082 | && handles == 0 | 1164 | && handles == 0 |
@@ -1090,6 +1172,9 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, | |||
1090 | GNUNET_break (0); | 1172 | GNUNET_break (0); |
1091 | } | 1173 | } |
1092 | #ifndef MINGW | 1174 | #ifndef MINGW |
1175 | tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value; | ||
1176 | tv.tv_usec = | ||
1177 | 1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value)); | ||
1093 | return select (nfds, | 1178 | return select (nfds, |
1094 | (rfds != NULL) ? &rfds->sds : NULL, | 1179 | (rfds != NULL) ? &rfds->sds : NULL, |
1095 | (wfds != NULL) ? &wfds->sds : NULL, | 1180 | (wfds != NULL) ? &wfds->sds : NULL, |
@@ -1098,332 +1183,441 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, | |||
1098 | ? NULL : &tv); | 1183 | ? NULL : &tv); |
1099 | 1184 | ||
1100 | #else | 1185 | #else |
1101 | DWORD limit; | ||
1102 | fd_set sock_read, sock_write, sock_except; | ||
1103 | fd_set aread, awrite, aexcept; | ||
1104 | struct GNUNET_CONTAINER_SList *handles_read, *handles_write, | ||
1105 | *handles_except; | ||
1106 | |||
1107 | int i; | ||
1108 | struct timeval tvslice; | ||
1109 | int retcode; | ||
1110 | DWORD ms_total; | ||
1111 | /* Number of milliseconds per cycle. Adapted on the fly */ | ||
1112 | static unsigned int cycle_delay = 20; | ||
1113 | |||
1114 | #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) | 1186 | #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) |
1115 | |||
1116 | /* calculate how long we need to wait in milliseconds */ | 1187 | /* calculate how long we need to wait in milliseconds */ |
1117 | if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) | 1188 | if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) |
1118 | ms_total = INFINITE; | 1189 | ms_total = INFINITE; |
1119 | |||
1120 | else | 1190 | else |
1121 | ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value; | 1191 | ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value; |
1122 | |||
1123 | /* select() may be used as a portable way to sleep */ | 1192 | /* select() may be used as a portable way to sleep */ |
1124 | if (!(rfds || wfds || efds)) | 1193 | if (!(rfds || wfds || efds)) |
1125 | |||
1126 | { | 1194 | { |
1127 | Sleep (ms_total); | 1195 | Sleep (ms_total); |
1128 | return 0; | 1196 | return 0; |
1129 | } | 1197 | } |
1130 | 1198 | ||
1131 | handles_read = GNUNET_CONTAINER_slist_create (); | 1199 | /* Events for sockets */ |
1132 | handles_write = GNUNET_CONTAINER_slist_create (); | 1200 | if (!hEventRead) |
1133 | handles_except = GNUNET_CONTAINER_slist_create (); | 1201 | hEventRead = CreateEvent (NULL, TRUE, FALSE, NULL); |
1134 | |||
1135 | if (rfds) | ||
1136 | sock_read = rfds->sds; | ||
1137 | else | 1202 | else |
1138 | FD_ZERO (&sock_read); | 1203 | ResetEvent (hEventRead); |
1139 | if (wfds) | 1204 | if (!hEventReadReady) |
1140 | sock_write = wfds->sds; | 1205 | hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL); |
1206 | if (!hEventWrite) | ||
1207 | hEventWrite = CreateEvent (NULL, TRUE, FALSE, NULL); | ||
1141 | else | 1208 | else |
1142 | FD_ZERO (&sock_write); | 1209 | ResetEvent (hEventWrite); |
1143 | if (efds) | 1210 | if (!hEventException) |
1144 | sock_except = efds->sds; | 1211 | hEventException = CreateEvent (NULL, TRUE, FALSE, NULL); |
1145 | else | 1212 | else |
1146 | FD_ZERO (&sock_except); | 1213 | ResetEvent (hEventException); |
1147 | 1214 | ||
1148 | /* multiplex between winsock select() and waiting on the handles */ | 1215 | /* Event for pipes */ |
1216 | if (!hEventPipeWrite) | ||
1217 | hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL); | ||
1218 | readPipes = 0; | ||
1219 | writePipePos = -1; | ||
1220 | |||
1221 | handles_read = GNUNET_CONTAINER_slist_create (); | ||
1222 | handles_write = GNUNET_CONTAINER_slist_create (); | ||
1223 | handles_except = GNUNET_CONTAINER_slist_create (); | ||
1149 | FD_ZERO (&aread); | 1224 | FD_ZERO (&aread); |
1150 | FD_ZERO (&awrite); | 1225 | FD_ZERO (&awrite); |
1151 | FD_ZERO (&aexcept); | 1226 | FD_ZERO (&aexcept); |
1152 | 1227 | #if DEBUG_NETWORK | |
1153 | #if DEBUG_W32_CYCLES | 1228 | FD_ZERO (&bread); |
1154 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1229 | FD_ZERO (&bwrite); |
1155 | "Starting a cycle, delay is %dms. nfds is %d.\n", cycle_delay, nfds); | 1230 | FD_ZERO (&bexcept); |
1156 | #endif | 1231 | #endif |
1157 | 1232 | if (rfds) | |
1158 | limit = GetTickCount () + ms_total; | 1233 | { |
1159 | 1234 | FD_COPY (&rfds->sds, &aread); | |
1160 | do | 1235 | #if DEBUG_NETWORK |
1161 | { | 1236 | FD_COPY (&rfds->sds, &bread); |
1162 | retcode = 0; | ||
1163 | if (nfds > 0) | ||
1164 | |||
1165 | { | ||
1166 | |||
1167 | /* overwrite the zero'd sets here; the select call | ||
1168 | * will clear those that are not active */ | ||
1169 | FD_COPY (&sock_read, &aread); | ||
1170 | FD_COPY (&sock_write, &awrite); | ||
1171 | FD_COPY (&sock_except, &aexcept); | ||
1172 | tvslice.tv_sec = 0; | ||
1173 | tvslice.tv_usec = cycle_delay; | ||
1174 | #if DEBUG_W32_CYCLES | ||
1175 | { | ||
1176 | for (i = 0; i < nfds; i++) | ||
1177 | { | ||
1178 | if (SAFE_FD_ISSET (i, &sock_read)) | ||
1179 | { | ||
1180 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1181 | "Going to select socket %d for reading\n", i); | ||
1182 | } | ||
1183 | if (SAFE_FD_ISSET (i, &sock_write)) | ||
1184 | { | ||
1185 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1186 | "Going to select socket %d for writing\n", i); | ||
1187 | } | ||
1188 | if (SAFE_FD_ISSET (i, &sock_except)) | ||
1189 | { | ||
1190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1191 | "Going to select socket %d for exceptions\n", i); | ||
1192 | } | ||
1193 | } | ||
1194 | } | ||
1195 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1196 | "Waiting for %d microseconds, %d left\n", cycle_delay, (limit - GetTickCount ())*1000); | ||
1197 | #endif | 1237 | #endif |
1198 | if ((retcode = | 1238 | } |
1199 | select (nfds + 1, &aread, &awrite, &aexcept, | 1239 | if (wfds) |
1200 | &tvslice)) == SOCKET_ERROR) | 1240 | { |
1201 | 1241 | FD_COPY (&wfds->sds, &awrite); | |
1202 | { | ||
1203 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
1204 | if (errno == ENOTSOCK) | ||
1205 | errno = EBADF; | ||
1206 | |||
1207 | #if DEBUG_NETWORK | 1242 | #if DEBUG_NETWORK |
1208 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select"); | 1243 | FD_COPY (&wfds->sds, &bwrite); |
1209 | 1244 | #endif | |
1245 | } | ||
1246 | if (efds) | ||
1247 | { | ||
1248 | FD_COPY (&efds->sds, &aexcept); | ||
1249 | #if DEBUG_NETWORK | ||
1250 | FD_COPY (&efds->sds, &bexcept); | ||
1210 | #endif | 1251 | #endif |
1211 | goto select_loop_end; | 1252 | } |
1212 | } | 1253 | /* We will first Add the PIPES to the events */ |
1213 | #if DEBUG_W32_CYCLES | 1254 | /* Read Pipes */ |
1214 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1255 | if (rfds && read_handles) |
1215 | "Select () returned %d, GLE is %d\n", retcode, GetLastError ()); | 1256 | { |
1257 | struct GNUNET_CONTAINER_SList_Iterator *i; | ||
1258 | for (i = GNUNET_CONTAINER_slist_begin (rfds->handles); | ||
1259 | GNUNET_CONTAINER_slist_end (i) != GNUNET_YES; | ||
1260 | GNUNET_CONTAINER_slist_next (i)) | ||
1261 | { | ||
1262 | struct GNUNET_DISK_FileHandle *fh; | ||
1263 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); | ||
1264 | if (fh->type == GNUNET_PIPE) | ||
1265 | { | ||
1266 | /* Read zero bytes to check the status of the pipe */ | ||
1267 | #if DEBUG_NETWORK | ||
1268 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n", fh->h); | ||
1216 | #endif | 1269 | #endif |
1217 | } | 1270 | if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead)) |
1218 | |||
1219 | /* Poll read pipes */ | ||
1220 | if (rfds) | ||
1221 | { | ||
1222 | struct GNUNET_CONTAINER_SList_Iterator *i; | ||
1223 | #if DEBUG_W32_CYCLES | ||
1224 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1225 | "Polling rfds for readable pipes\n"); | ||
1226 | #endif | ||
1227 | for (i = GNUNET_CONTAINER_slist_begin (rfds->handles); | ||
1228 | GNUNET_CONTAINER_slist_end (i) != GNUNET_YES; | ||
1229 | GNUNET_CONTAINER_slist_next (i)) | ||
1230 | |||
1231 | { | ||
1232 | struct GNUNET_DISK_FileHandle *fh; | ||
1233 | DWORD dwBytes; | ||
1234 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); | ||
1235 | if (fh->type == GNUNET_PIPE) | ||
1236 | { | ||
1237 | #if DEBUG_W32_CYCLES | ||
1238 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1239 | "Polling pipe 0x%x (0x%x)\n", fh, fh->h); | ||
1240 | #endif | ||
1241 | if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) | ||
1242 | { | ||
1243 | DWORD error_code = GetLastError (); | ||
1244 | switch (error_code) | ||
1245 | { | ||
1246 | case ERROR_BROKEN_PIPE: | ||
1247 | GNUNET_CONTAINER_slist_add (handles_read, | ||
1248 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1249 | fh, sizeof (struct GNUNET_DISK_FileHandle)); | ||
1250 | retcode++; | ||
1251 | break; | ||
1252 | default: | ||
1253 | retcode = -1; | ||
1254 | SetErrnoFromWinError (error_code); | ||
1255 | |||
1256 | #if DEBUG_NETWORK | ||
1257 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
1258 | "PeekNamedPipe"); | ||
1259 | |||
1260 | #endif | ||
1261 | goto select_loop_end; | ||
1262 | } | ||
1263 | } | ||
1264 | else if (dwBytes) | ||
1265 | |||
1266 | { | ||
1267 | GNUNET_CONTAINER_slist_add (handles_read, | ||
1268 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1269 | fh, sizeof (struct GNUNET_DISK_FileHandle)); | ||
1270 | retcode++; | ||
1271 | } | ||
1272 | } | ||
1273 | else | ||
1274 | { | ||
1275 | /* Should we wait for more bytes to read here (in case of previous EOF)? */ | ||
1276 | GNUNET_CONTAINER_slist_add (handles_read, | ||
1277 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1278 | fh, sizeof (struct GNUNET_DISK_FileHandle)); | ||
1279 | } | ||
1280 | } | ||
1281 | GNUNET_CONTAINER_slist_iter_destroy (i); | ||
1282 | } | ||
1283 | |||
1284 | /* Poll for faulty pipes */ | ||
1285 | if (efds) | ||
1286 | |||
1287 | { | 1271 | { |
1288 | #if DEBUG_W32_CYCLES | 1272 | DWORD error_code = GetLastError(); |
1289 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1273 | if (error_code == ERROR_IO_PENDING) |
1290 | "Polling efds for broken pipes\n"); | 1274 | { |
1291 | #endif | 1275 | #if DEBUG_NETWORK |
1292 | struct GNUNET_CONTAINER_SList_Iterator *i; | 1276 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the pipe's 0x%x overlapped event to the array as %d\n", fh->h, nhandles); |
1293 | for (i = GNUNET_CONTAINER_slist_begin (efds->handles); | 1277 | #endif |
1294 | GNUNET_CONTAINER_slist_end (i) != GNUNET_YES; | 1278 | handle_array[nhandles++] = fh->oOverlapRead->hEvent; |
1295 | GNUNET_CONTAINER_slist_next (i)) | 1279 | readArray[readPipes++] = fh; |
1296 | 1280 | } | |
1297 | { | 1281 | /* |
1298 | struct GNUNET_DISK_FileHandle *fh; | 1282 | else |
1299 | DWORD dwBytes; | 1283 | { |
1300 | 1284 | SetErrnoFromWinError (error_code); | |
1301 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); | 1285 | } |
1302 | if (fh->type == GNUNET_PIPE) | 1286 | */ |
1303 | { | ||
1304 | #if DEBUG_W32_CYCLES | ||
1305 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1306 | "Polling pipe 0x%x (0x%x)\n", fh, fh->h); | ||
1307 | #endif | ||
1308 | if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) | ||
1309 | |||
1310 | { | ||
1311 | GNUNET_CONTAINER_slist_add (handles_except, | ||
1312 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1313 | fh, sizeof (struct GNUNET_DISK_FileHandle)); | ||
1314 | retcode++; | ||
1315 | } | ||
1316 | } | ||
1317 | } | ||
1318 | GNUNET_CONTAINER_slist_iter_destroy (i); | ||
1319 | } | 1287 | } |
1320 | 1288 | else | |
1321 | if (wfds) | ||
1322 | { | 1289 | { |
1323 | GNUNET_CONTAINER_slist_append (handles_write, wfds->handles); | 1290 | #if DEBUG_NETWORK |
1324 | retcode += GNUNET_CONTAINER_slist_count (wfds->handles); | 1291 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the read ready event to the array as %d\n", nhandles); |
1292 | #endif | ||
1293 | handle_array[nhandles++] = hEventReadReady; | ||
1294 | readArray[readPipes++] = fh; | ||
1325 | } | 1295 | } |
1296 | } | ||
1297 | else | ||
1298 | { | ||
1299 | GNUNET_CONTAINER_slist_add (handles_read, | ||
1300 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1301 | fh, sizeof (struct GNUNET_DISK_FileHandle)); | ||
1302 | } | ||
1303 | } | ||
1304 | GNUNET_CONTAINER_slist_iter_destroy (i); | ||
1305 | } | ||
1306 | if (wfds && write_handles) | ||
1307 | { | ||
1308 | #if DEBUG_NETWORK | ||
1309 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the write ready event to the array as %d\n", nhandles); | ||
1310 | #endif | ||
1311 | handle_array[nhandles++] = hEventPipeWrite; | ||
1312 | writePipePos = nhandles; | ||
1313 | } | ||
1314 | if (efds && ex_handles) | ||
1315 | { | ||
1316 | struct GNUNET_CONTAINER_SList_Iterator *i; | ||
1317 | for (i = GNUNET_CONTAINER_slist_begin (efds->handles); | ||
1318 | GNUNET_CONTAINER_slist_end (i) != GNUNET_YES; | ||
1319 | GNUNET_CONTAINER_slist_next (i)) | ||
1320 | { | ||
1321 | struct GNUNET_DISK_FileHandle *fh; | ||
1322 | DWORD dwBytes; | ||
1326 | 1323 | ||
1327 | /* Check for closed sockets */ | 1324 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); |
1328 | for (i = 0; i < nfds; i++) | 1325 | if (fh->type == GNUNET_PIPE) |
1329 | 1326 | { | |
1327 | if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) | ||
1330 | { | 1328 | { |
1331 | if (SAFE_FD_ISSET (i, &sock_read)) | 1329 | GNUNET_CONTAINER_slist_add (handles_except, |
1332 | 1330 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | |
1333 | { | 1331 | fh, sizeof (struct GNUNET_DISK_FileHandle)); |
1334 | struct sockaddr addr; | 1332 | newretcode++; |
1335 | int len; | ||
1336 | if (getpeername (i, &addr, &len) == SOCKET_ERROR) | ||
1337 | |||
1338 | { | ||
1339 | int err, len; | ||
1340 | len = sizeof (err); | ||
1341 | if (getsockopt | ||
1342 | (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0 | ||
1343 | && err == WSAENOTCONN) | ||
1344 | |||
1345 | { | ||
1346 | if (!SAFE_FD_ISSET (i, &aread)) | ||
1347 | |||
1348 | { | ||
1349 | FD_SET (i, &aread); | ||
1350 | retcode++; | ||
1351 | } | ||
1352 | } | ||
1353 | } | ||
1354 | } | ||
1355 | } | 1333 | } |
1356 | select_loop_end: | 1334 | } |
1357 | if (retcode == 0) | 1335 | } |
1336 | GNUNET_CONTAINER_slist_iter_destroy (i); | ||
1337 | } | ||
1338 | if (nfds > 0) | ||
1339 | { | ||
1340 | if (rfds) | ||
1341 | { | ||
1342 | #if DEBUG_NETWORK | ||
1343 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket read event to the array as %d\n", nhandles); | ||
1344 | #endif | ||
1345 | handle_array[nhandles++] = hEventRead; | ||
1346 | nSockEvents++; | ||
1347 | for (i = 0; i < rfds->sds.fd_count; i++) | ||
1348 | { | ||
1349 | WSAEventSelect (rfds->sds.fd_array[i], hEventRead, FD_ACCEPT | FD_READ | FD_CLOSE); | ||
1350 | nsock++; | ||
1351 | } | ||
1352 | } | ||
1353 | if (wfds) | ||
1354 | { | ||
1355 | int wakeup = 0; | ||
1356 | #if DEBUG_NETWORK | ||
1357 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket write event to the array as %d\n", nhandles); | ||
1358 | #endif | ||
1359 | handle_array[nhandles++] = hEventWrite; | ||
1360 | nSockEvents++; | ||
1361 | for (i = 0; i < wfds->sds.fd_count; i++) | ||
1358 | { | 1362 | { |
1359 | /* For pipes, there have been no select() call, so the poll is | 1363 | DWORD error; |
1360 | * more likely to miss first time around. For now just don't increase | 1364 | int status; |
1361 | * the delay for pipes only. | 1365 | status = send (wfds->sds.fd_array[i], NULL, 0, 0); |
1362 | */ | 1366 | error = GetLastError (); |
1363 | if (nfds != 0) | 1367 | #if DEBUG_NETWORK |
1364 | cycle_delay = cycle_delay * 2 > 250000 ? 250000 : cycle_delay * 1.4; | 1368 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pre-send to the socket %d returned %d (%u)\n", i, status, error); |
1365 | /* Missed an I/O - double the cycle time */ | ||
1366 | #if DEBUG_W32_CYCLES | ||
1367 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1368 | "The cycle missed, increased the delay to %dms\n", cycle_delay); | ||
1369 | #endif | 1369 | #endif |
1370 | if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN)) | ||
1371 | wakeup = 1; | ||
1372 | WSAEventSelect (wfds->sds.fd_array[i], hEventWrite, FD_WRITE | FD_CONNECT | FD_CLOSE); | ||
1373 | nsock++; | ||
1370 | } | 1374 | } |
1371 | else | 1375 | if (wakeup) |
1376 | SetEvent (hEventWrite); | ||
1377 | } | ||
1378 | if (efds) | ||
1379 | { | ||
1380 | #if DEBUG_NETWORK | ||
1381 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket error event to the array as %d\n", nhandles); | ||
1382 | #endif | ||
1383 | handle_array[nhandles++] = hEventException; | ||
1384 | nSockEvents++; | ||
1385 | for (i = 0; i < efds->sds.fd_count; i++) | ||
1372 | { | 1386 | { |
1373 | /* Successfully selected something - decrease the cycle time */ | 1387 | WSAEventSelect (efds->sds.fd_array[i], hEventException, FD_OOB | FD_CLOSE); |
1374 | /* Minimum is 5 microseconds. Decrease the delay by half, | 1388 | nsock++; |
1375 | * or by 5000 - whichever is higher. | 1389 | } |
1376 | */ | 1390 | } |
1377 | cycle_delay -= cycle_delay > 5000 ? GNUNET_MAX (5000, cycle_delay / 2) : cycle_delay - 5; | 1391 | } |
1378 | #if DEBUG_W32_CYCLES | 1392 | |
1379 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1393 | handle_array[nhandles] = NULL; |
1380 | "The cycle hit, decreased the delay to %dms\n", cycle_delay); | 1394 | |
1395 | #if DEBUG_NETWORK | ||
1396 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Number nfds : %d\n", nfds); | ||
1397 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Number of handles : %d\n", nhandles); | ||
1398 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "retcode : %d\n", newretcode); | ||
1399 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will wait : %d\n", ms_total); | ||
1400 | #endif | ||
1401 | |||
1402 | if (nhandles) | ||
1403 | returncode = WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total); | ||
1404 | #if DEBUG_NETWORK | ||
1405 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode); | ||
1406 | #endif | ||
1407 | |||
1408 | returnedpos = returncode - WAIT_OBJECT_0; | ||
1409 | #if DEBUG_NETWORK | ||
1410 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos); | ||
1411 | #endif | ||
1412 | |||
1413 | /* FIXME: THIS LINE IS WRONG !! We should add to handles only handles that fired the events, not all ! */ | ||
1414 | /* | ||
1415 | if(rfds) | ||
1416 | GNUNET_CONTAINER_slist_append (handles_read, rfds->handles); | ||
1417 | */ | ||
1418 | if (nhandles && (returnedpos < nhandles)) | ||
1419 | { | ||
1420 | DWORD waitstatus; | ||
1421 | /* Do the select */ | ||
1422 | if (nfds) | ||
1423 | { | ||
1424 | struct timeval tvslice; | ||
1425 | tvslice.tv_sec = 0; | ||
1426 | tvslice.tv_usec = 10; | ||
1427 | retcode = select (nfds, &aread, &awrite, &aexcept, &tvslice); | ||
1428 | if (retcode == -1) | ||
1429 | retcode = 0; | ||
1430 | #if DEBUG_NETWORK | ||
1431 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Select retcode : %d\n", retcode); | ||
1381 | #endif | 1432 | #endif |
1433 | } | ||
1434 | /* FIXME: <= writePipePos? Really? */ | ||
1435 | if ((writePipePos != -1) && (returnedpos <= writePipePos)) | ||
1436 | { | ||
1437 | GNUNET_CONTAINER_slist_append (handles_write, wfds->handles); | ||
1438 | retcode += write_handles; | ||
1439 | #if DEBUG_NETWORK | ||
1440 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n"); | ||
1441 | #endif | ||
1442 | } | ||
1443 | #if DEBUG_NETWORK | ||
1444 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes); | ||
1445 | #endif | ||
1446 | /* We have some pipes ready for read. */ | ||
1447 | /* FIXME: it is supposed to work !! Only choose the Pipes who fired the event, but it is not working */ | ||
1448 | |||
1449 | if (returnedpos < readPipes) | ||
1450 | { | ||
1451 | /* | ||
1452 | for (i = 0; i < readPipes; i++) | ||
1453 | { | ||
1454 | waitstatus = WaitForSingleObject (handle_array[i], 0); | ||
1455 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read pipe %d wait status is : %d\n", i, waitstatus); | ||
1456 | if (waitstatus != WAIT_OBJECT_0) | ||
1457 | continue; | ||
1458 | GNUNET_CONTAINER_slist_add (handles_read, | ||
1459 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1460 | readArray[i], sizeof (struct GNUNET_DISK_FileHandle)); | ||
1461 | retcode++; | ||
1462 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe\n"); | ||
1382 | } | 1463 | } |
1383 | if (retcode == 0 && nfds == 0) | 1464 | */ |
1465 | for (i = 0; i < readPipes; i++) | ||
1384 | { | 1466 | { |
1385 | long long diff = limit - GetTickCount (); | 1467 | DWORD error; |
1386 | diff = diff > 0 ? diff : 0; | 1468 | BOOL bret; |
1387 | #if DEBUG_W32_CYCLES | 1469 | SetLastError (0); |
1388 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1470 | waitstatus = 0; |
1389 | "No sockets, sleeping for %d or %d ms\n", cycle_delay / 1000, diff); | 1471 | bret = PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL); |
1472 | error = GetLastError (); | ||
1473 | #if DEBUG_NETWORK | ||
1474 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n", i, readArray[i]->h, bret, waitstatus, error); | ||
1475 | #endif | ||
1476 | if (bret == 0 || waitstatus <= 0) | ||
1477 | continue; | ||
1478 | GNUNET_CONTAINER_slist_add (handles_read, | ||
1479 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1480 | readArray[i], sizeof (struct GNUNET_DISK_FileHandle)); | ||
1481 | retcode++; | ||
1482 | #if DEBUG_NETWORK | ||
1483 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n", readArray[i], readArray[i]->h); | ||
1390 | #endif | 1484 | #endif |
1391 | Sleep (GNUNET_MIN (cycle_delay / 1000, diff)); | ||
1392 | } | 1485 | } |
1393 | } | 1486 | } |
1394 | while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit)); | 1487 | waitstatus = WaitForSingleObject (hEventWrite, 0); |
1395 | 1488 | #if DEBUG_NETWORK | |
1396 | if (retcode != -1) | 1489 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wait for the write event returned %d\n", waitstatus); |
1490 | #endif | ||
1491 | if (waitstatus == WAIT_OBJECT_0) | ||
1397 | { | 1492 | { |
1398 | if (rfds) | 1493 | for (i = 0; i < wfds->sds.fd_count; i++) |
1399 | { | 1494 | { |
1400 | GNUNET_NETWORK_fdset_zero (rfds); | 1495 | DWORD error; |
1401 | GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode); | 1496 | int status; |
1402 | GNUNET_CONTAINER_slist_clear (rfds->handles); | 1497 | int so_error = 0; |
1403 | GNUNET_CONTAINER_slist_append (rfds->handles, handles_read); | 1498 | int sizeof_so_error = sizeof (so_error); |
1404 | } | 1499 | int gso_result = getsockopt (wfds->sds.fd_array[i], SOL_SOCKET, SO_ERROR, (char *) &so_error, &sizeof_so_error); |
1405 | if (wfds) | 1500 | status = send (wfds->sds.fd_array[i], NULL, 0, 0); |
1406 | { | 1501 | error = GetLastError (); |
1407 | GNUNET_NETWORK_fdset_zero (wfds); | 1502 | #if DEBUG_NETWORK |
1408 | GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode); | 1503 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "send to the socket %d returned %d (%u)\n", i, status, error); |
1409 | GNUNET_CONTAINER_slist_clear (wfds->handles); | 1504 | #endif |
1410 | GNUNET_CONTAINER_slist_append (wfds->handles, handles_write); | 1505 | if (status == 0 |
1411 | } | 1506 | || (error != WSAEWOULDBLOCK && error != WSAENOTCONN) |
1412 | if (efds) | 1507 | || (status == -1 && gso_result == 0 && error == WSAENOTCONN && so_error == WSAECONNREFUSED)) |
1413 | { | 1508 | { |
1414 | GNUNET_NETWORK_fdset_zero (efds); | 1509 | FD_SET (wfds->sds.fd_array[i], &awrite); |
1415 | GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode); | 1510 | retcode += 1; |
1416 | GNUNET_CONTAINER_slist_clear (efds->handles); | ||
1417 | GNUNET_CONTAINER_slist_append (efds->handles, handles_except); | ||
1418 | } | 1511 | } |
1512 | } | ||
1419 | } | 1513 | } |
1420 | 1514 | } | |
1515 | #if DEBUG_NETWORK | ||
1516 | if (!nhandles || (returnedpos >= nhandles)) | ||
1517 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n"); | ||
1518 | #endif | ||
1519 | if (rfds) | ||
1520 | { | ||
1521 | struct GNUNET_CONTAINER_SList_Iterator *t; | ||
1522 | for (i = 0; i < rfds->sds.fd_count; i++) | ||
1523 | { | ||
1524 | WSAEventSelect (rfds->sds.fd_array[i], hEventRead, 0); | ||
1525 | nsock++; | ||
1526 | } | ||
1527 | for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); | ||
1528 | GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; | ||
1529 | GNUNET_CONTAINER_slist_next (t)) | ||
1530 | { | ||
1531 | struct GNUNET_DISK_FileHandle *fh; | ||
1532 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL); | ||
1533 | if (fh->type == GNUNET_PIPE) | ||
1534 | { | ||
1535 | CancelIo (fh->h); | ||
1536 | } | ||
1537 | } | ||
1538 | GNUNET_CONTAINER_slist_iter_destroy (t); | ||
1539 | #if DEBUG_NETWORK | ||
1540 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds\n"); | ||
1541 | #endif | ||
1542 | GNUNET_NETWORK_fdset_zero (rfds); | ||
1543 | if (retcode != -1 && nhandles && (returnedpos < nhandles)) | ||
1544 | GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode); | ||
1545 | GNUNET_CONTAINER_slist_append (rfds->handles, handles_read); | ||
1546 | } | ||
1547 | if (wfds) | ||
1548 | { | ||
1549 | for (i = 0; i < wfds->sds.fd_count; i++) | ||
1550 | { | ||
1551 | WSAEventSelect (wfds->sds.fd_array[i], hEventWrite, 0); | ||
1552 | nsock++; | ||
1553 | } | ||
1554 | #if DEBUG_NETWORK | ||
1555 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds\n"); | ||
1556 | #endif | ||
1557 | GNUNET_NETWORK_fdset_zero (wfds); | ||
1558 | if (retcode != -1 && nhandles && (returnedpos < nhandles)) | ||
1559 | GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode); | ||
1560 | GNUNET_CONTAINER_slist_append (wfds->handles, handles_write); | ||
1561 | } | ||
1562 | if (efds) | ||
1563 | { | ||
1564 | for (i = 0; i < efds->sds.fd_count; i++) | ||
1565 | { | ||
1566 | WSAEventSelect (efds->sds.fd_array[i], hEventException, 0); | ||
1567 | nsock++; | ||
1568 | } | ||
1569 | #if DEBUG_NETWORK | ||
1570 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds\n"); | ||
1571 | #endif | ||
1572 | GNUNET_NETWORK_fdset_zero (efds); | ||
1573 | if (retcode != -1 && nhandles && (returnedpos < nhandles)) | ||
1574 | GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode); | ||
1575 | GNUNET_CONTAINER_slist_append (efds->handles, handles_except); | ||
1576 | } | ||
1421 | GNUNET_CONTAINER_slist_destroy (handles_read); | 1577 | GNUNET_CONTAINER_slist_destroy (handles_read); |
1422 | GNUNET_CONTAINER_slist_destroy (handles_write); | 1578 | GNUNET_CONTAINER_slist_destroy (handles_write); |
1423 | GNUNET_CONTAINER_slist_destroy (handles_except); | 1579 | GNUNET_CONTAINER_slist_destroy (handles_except); |
1424 | 1580 | #if DEBUG_NETWORK | |
1425 | return retcode; | 1581 | if (rfds) |
1582 | { | ||
1583 | struct GNUNET_CONTAINER_SList_Iterator *t; | ||
1584 | for (i = 0; i < bread.fd_count; i++) | ||
1585 | { | ||
1586 | if (bread.fd_array[i] != 0) | ||
1587 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in rfds\n", bread.fd_array[i], (SAFE_FD_ISSET (bread.fd_array[i], rfds)) ? "SET" : "NOT SET"); | ||
1588 | } | ||
1589 | for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); | ||
1590 | GNUNET_CONTAINER_slist_end (t) != GNUNET_YES; | ||
1591 | GNUNET_CONTAINER_slist_next (t)) | ||
1592 | { | ||
1593 | struct GNUNET_DISK_FileHandle *fh; | ||
1594 | fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL); | ||
1595 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is SET in rfds\n", fh->h); | ||
1596 | } | ||
1597 | } | ||
1598 | if (wfds) | ||
1599 | { | ||
1600 | for (i = 0; i < bwrite.fd_count; i++) | ||
1601 | { | ||
1602 | if (bwrite.fd_array[i] != 0) | ||
1603 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in wfds\n", bwrite.fd_array[i], (SAFE_FD_ISSET (bwrite.fd_array[i], rfds)) ? "SET" : "NOT SET"); | ||
1604 | } | ||
1605 | } | ||
1606 | if (efds) | ||
1607 | { | ||
1608 | for (i = 0; i < bexcept.fd_count; i++) | ||
1609 | { | ||
1610 | if (bexcept.fd_array[i] != 0) | ||
1611 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in efds\n", bexcept.fd_array[i], (SAFE_FD_ISSET (bexcept.fd_array[i], rfds)) ? "SET" : "NOT SET"); | ||
1612 | } | ||
1613 | } | ||
1614 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode); | ||
1615 | #endif | ||
1616 | if (nhandles && (returnedpos < nhandles)) | ||
1617 | return retcode; | ||
1618 | else | ||
1426 | #endif | 1619 | #endif |
1620 | return 0; | ||
1427 | } | 1621 | } |
1428 | 1622 | ||
1429 | 1623 | ||