aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-08-01 20:32:59 +0000
committerChristian Grothoff <christian@grothoff.org>2011-08-01 20:32:59 +0000
commitff2d2e7ea5f470af1c345e7c66fe320d4c9d2d33 (patch)
tree4a279a987a23b018ff568099759e87d6e6b09354 /src/util
parent87f795e4d28eee0ae57f9d916ef12141937e4b4a (diff)
downloadgnunet-ff2d2e7ea5f470af1c345e7c66fe320d4c9d2d33.tar.gz
gnunet-ff2d2e7ea5f470af1c345e7c66fe320d4c9d2d33.zip
LRN: Bratao's select() implementation for W32
Diffstat (limited to 'src/util')
-rw-r--r--src/util/disk.c217
-rw-r--r--src/util/disk.h10
-rw-r--r--src/util/network.c778
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
62ULONG 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. */
1708static int
1709create_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