Socket support rewritten. It was utterly broken, and untested in fact. We
[platform/upstream/glib.git] / giowin32.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * giowin32.c: IO Channels for Win32.
5  * Copyright 1998 Owen Taylor and Tor Lillqvist
6  * Copyright 1999-2000 Tor Lillqvist and Craig Setera
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /*
25  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
26  * file for a list of people on the GLib Team.  See the ChangeLog
27  * files for a list of changes.  These files are distributed with
28  * GLib at ftp://ftp.gtk.org/pub/gtk/.
29  */
30
31 /* Define this to get (very) verbose logging of all channels */
32 /* #define G_IO_WIN32_DEBUG */
33
34 #include "glib.h"
35
36 #include <stdlib.h>
37 #include <windows.h>
38 #include <winsock.h>          /* Not everybody has winsock2 */
39 #include <fcntl.h>
40 #include <io.h>
41 #include <process.h>
42 #include <errno.h>
43 #include <sys/stat.h>
44
45 typedef struct _GIOWin32Channel GIOWin32Channel;
46 typedef struct _GIOWin32Watch GIOWin32Watch;
47
48 #define BUFFER_SIZE 4096
49
50 typedef enum {
51   G_IO_WIN32_WINDOWS_MESSAGES,  /* Windows messages */
52   G_IO_WIN32_FILE_DESC,         /* Unix-like file descriptors from
53                                  * _open() or _pipe(). Read with read().
54                                  * Have to create separate thread to read.
55                                  */
56   G_IO_WIN32_SOCKET             /* Sockets. A separate thread is blocked
57                                  * in select() most of the time.
58                                  */
59 } GIOWin32ChannelType;
60
61 struct _GIOWin32Channel {
62   GIOChannel channel;
63   gint fd;                      /* Either a Unix-like file handle as provided
64                                  * by the Microsoft C runtime, or a SOCKET
65                                  * as provided by WinSock.
66                                  */
67   GIOWin32ChannelType type;
68   
69   gboolean debug;
70
71   CRITICAL_SECTION mutex;
72
73   /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
74   HWND hwnd;                    /* handle of window, or NULL */
75   
76   /* Following fields are used by both fd and socket channels. */
77   gboolean running;             /* Is reader thread running. FALSE if
78                                  * EOF has been reached.
79                                  */
80   gboolean needs_close;         /* If the channel has been closed while
81                                  * the reader thread was still running.
82                                  */
83   guint thread_id;              /* If non-NULL has a reader thread, or has
84                                  * had.*/
85   HANDLE thread_handle;
86   HANDLE data_avail_event;
87
88   gushort revents;
89
90   /* Following fields used by fd channels for input */
91   
92   /* Data is kept in a circular buffer. To be able to distinguish between
93    * empty and full buffer, we cannot fill it completely, but have to
94    * leave a one character gap.
95    *
96    * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
97    *
98    * Empty:    wrp == rdp
99    * Full:     (wrp + 1) % BUFFER_SIZE == rdp
100    * Partial:  otherwise
101    */
102   guchar *buffer;               /* (Circular) buffer */
103   gint wrp, rdp;                /* Buffer indices for writing and reading */
104   HANDLE space_avail_event;
105
106   /* Following fields used by socket channels */
107   GSList *watches;
108   HANDLE data_avail_noticed_event;
109 };
110
111 #define LOCK(mutex) EnterCriticalSection (&mutex)
112 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
113
114 struct _GIOWin32Watch {
115   GSource       source;
116   GPollFD       pollfd;
117   GIOChannel   *channel;
118   GIOCondition  condition;
119   GIOFunc       callback;
120 };
121
122 static void
123 g_io_channel_win32_init (GIOWin32Channel *channel)
124 {
125 #ifdef G_IO_WIN32_DEBUG
126   channel->debug = TRUE;
127 #else
128   if (getenv ("G_IO_WIN32_DEBUG") != NULL)
129     channel->debug = TRUE;
130   else
131     channel->debug = FALSE;
132 #endif
133   channel->buffer = NULL;
134   channel->running = FALSE;
135   channel->needs_close = FALSE;
136   channel->thread_id = 0;
137   channel->data_avail_event = NULL;
138   channel->revents = 0;
139   channel->space_avail_event = NULL;
140   channel->data_avail_noticed_event = NULL;
141   channel->watches = NULL;
142   InitializeCriticalSection (&channel->mutex);
143 }
144
145 static void
146 create_events (GIOWin32Channel *channel)
147 {
148   SECURITY_ATTRIBUTES sec_attrs;
149   
150   sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
151   sec_attrs.lpSecurityDescriptor = NULL;
152   sec_attrs.bInheritHandle = FALSE;
153
154   /* The data available event is manual reset, the space available event
155    * is automatic reset.
156    */
157   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
158       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
159       || !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
160     {
161       gchar *msg = g_win32_error_message (GetLastError ());
162       g_error ("Error creating event: %s", msg);
163     }
164 }
165
166 static unsigned __stdcall
167 read_thread (void *parameter)
168 {
169   GIOWin32Channel *channel = parameter;
170   GSList *tmp;
171   guchar *buffer;
172   guint nbytes;
173
174   g_io_channel_ref ((GIOChannel *)channel);
175
176   if (channel->debug)
177     g_print ("read_thread %#x: start fd:%d, data_avail:%#x, space_avail:%#x\n",
178              channel->thread_id,
179              channel->fd,
180              (guint) channel->data_avail_event,
181              (guint) channel->space_avail_event);
182   
183   channel->buffer = g_malloc (BUFFER_SIZE);
184   channel->rdp = channel->wrp = 0;
185   channel->running = TRUE;
186
187   SetEvent (channel->space_avail_event);
188   
189   while (channel->running)
190     {
191       LOCK (channel->mutex);
192       if (channel->debug)
193         g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
194                  channel->thread_id, channel->rdp, channel->wrp);
195       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
196         {
197           /* Buffer is full */
198           if (channel->debug)
199             g_print ("read_thread %#x: resetting space_avail\n",
200                      channel->thread_id);
201           ResetEvent (channel->space_avail_event);
202           if (channel->debug)
203             g_print ("read_thread %#x: waiting for space\n",
204                      channel->thread_id);
205           UNLOCK (channel->mutex);
206           WaitForSingleObject (channel->space_avail_event, INFINITE);
207           LOCK (channel->mutex);
208           if (channel->debug)
209             g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
210                      channel->thread_id, channel->rdp, channel->wrp);
211         }
212       
213       buffer = channel->buffer + channel->wrp;
214       
215       /* Always leave at least one byte unused gap to be able to
216        * distinguish between the full and empty condition...
217        */
218       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
219                     BUFFER_SIZE - channel->wrp);
220
221       if (channel->debug)
222         g_print ("read_thread %#x: calling read() for %d bytes\n",
223                  channel->thread_id, nbytes);
224
225       UNLOCK (channel->mutex);
226
227       nbytes = read (channel->fd, buffer, nbytes);
228       
229       LOCK (channel->mutex);
230
231       channel->revents = G_IO_IN;
232       if (nbytes == 0)
233         channel->revents |= G_IO_HUP;
234       else if (nbytes < 0)
235         channel->revents |= G_IO_ERR;
236
237       if (channel->debug)
238         g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
239                  channel->thread_id, nbytes, channel->rdp, channel->wrp);
240
241       if (nbytes <= 0)
242         break;
243
244       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
245       if (channel->debug)
246         g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
247                  channel->thread_id, channel->rdp, channel->wrp);
248       SetEvent (channel->data_avail_event);
249       UNLOCK (channel->mutex);
250     }
251   
252   channel->running = FALSE;
253   if (channel->needs_close)
254     {
255       if (channel->debug)
256         g_print ("read_thread %#x: channel fd %d needs closing\n",
257                  channel->thread_id, channel->fd);
258       close (channel->fd);
259       channel->fd = -1;
260     }
261
262   if (channel->debug)
263     g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
264              channel->thread_id, channel->rdp, channel->wrp);
265   SetEvent (channel->data_avail_event);
266   UNLOCK (channel->mutex);
267   
268   g_io_channel_unref((GIOChannel *)channel);
269   
270   /* No need to call _endthreadex(), the actual thread starter routine
271    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
272    * _endthreadex() for us.
273    */
274
275   CloseHandle (channel->thread_handle);
276
277   return 0;
278 }
279
280 static void
281 create_thread (GIOWin32Channel     *channel,
282                GIOCondition         condition,
283                unsigned (__stdcall *thread) (void *parameter))
284 {
285   if ((channel->thread_handle =
286        (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
287                                 &channel->thread_id)) == 0)
288     g_warning ("Error creating reader thread: %s", strerror (errno));
289   WaitForSingleObject (channel->space_avail_event, INFINITE);
290 }
291
292 static int
293 buffer_read (GIOWin32Channel *channel,
294              guchar          *dest,
295              guint            count,
296              GIOError        *error)
297 {
298   guint nbytes;
299   guint left = count;
300   
301   LOCK (channel->mutex);
302   if (channel->debug)
303     g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
304              channel->thread_id, count, channel->rdp, channel->wrp);
305   
306   if (channel->wrp == channel->rdp)
307     {
308       UNLOCK (channel->mutex);
309       if (channel->debug)
310         g_print ("waiting for data from thread %#x\n", channel->thread_id);
311       WaitForSingleObject (channel->data_avail_event, INFINITE);
312       if (channel->debug)
313         g_print ("done waiting for data from thread %#x\n", channel->thread_id);
314       LOCK (channel->mutex);
315       if (channel->wrp == channel->rdp && !channel->running)
316         {
317           UNLOCK (channel->mutex);
318           return 0;
319         }
320     }
321   
322   if (channel->rdp < channel->wrp)
323     nbytes = channel->wrp - channel->rdp;
324   else
325     nbytes = BUFFER_SIZE - channel->rdp;
326   UNLOCK (channel->mutex);
327   nbytes = MIN (left, nbytes);
328   if (channel->debug)
329     g_print ("moving %d bytes from thread %#x\n",
330              nbytes, channel->thread_id);
331   memcpy (dest, channel->buffer + channel->rdp, nbytes);
332   dest += nbytes;
333   left -= nbytes;
334   LOCK (channel->mutex);
335   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
336   if (channel->debug)
337     g_print ("setting space_avail for thread %#x\n", channel->thread_id);
338   SetEvent (channel->space_avail_event);
339   if (channel->debug)
340     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
341              channel->thread_id, channel->rdp, channel->wrp);
342   if (channel->running && channel->wrp == channel->rdp)
343     {
344       if (channel->debug)
345         g_print ("resetting data_avail of thread %#x\n",
346                  channel->thread_id);
347       ResetEvent (channel->data_avail_event);
348     };
349   UNLOCK (channel->mutex);
350   
351   /* We have no way to indicate any errors form the actual
352    * read() or recv() call in the reader thread. Should we have?
353    */
354   *error = G_IO_ERROR_NONE;
355   return count - left;
356 }
357
358 static unsigned __stdcall
359 select_thread (void *parameter)
360 {
361   GIOWin32Channel *channel = parameter;
362   fd_set read_fds, write_fds, except_fds;
363   GSList *tmp;
364   int n;
365
366   g_io_channel_ref ((GIOChannel *)channel);
367
368   if (channel->debug)
369     g_print ("select_thread %#x: start fd:%d,\n\tdata_avail:%#x, data_avail_noticed:%#x\n",
370              channel->thread_id,
371              channel->fd,
372              (guint) channel->data_avail_event,
373              (guint) channel->data_avail_noticed_event);
374   
375   channel->rdp = channel->wrp = 0;
376   channel->running = TRUE;
377
378   SetEvent (channel->space_avail_event);
379   
380   while (channel->running)
381     {
382       FD_ZERO (&read_fds);
383       FD_ZERO (&write_fds);
384       FD_ZERO (&except_fds);
385
386       tmp = channel->watches;
387       while (tmp)
388         {
389           GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
390
391           if (watch->condition & (G_IO_IN | G_IO_HUP))
392             FD_SET (channel->fd, &read_fds);
393           if (watch->condition & G_IO_OUT)
394             FD_SET (channel->fd, &write_fds);
395           if (watch->condition & G_IO_ERR)
396             FD_SET (channel->fd, &except_fds);
397           
398           tmp = tmp->next;
399         }
400       if (channel->debug)
401         g_print ("select_thread %#x: calling select() for%s%s%s\n",
402                  channel->thread_id,
403                  (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
404                  (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
405                  (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
406
407       n = select (1, &read_fds, &write_fds, &except_fds, NULL);
408       
409       if (n == SOCKET_ERROR)
410         {
411           if (channel->debug)
412             g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
413                      channel->thread_id);
414           break;
415         }
416
417       if (channel->debug)
418         g_print ("select_thread %#x: got%s%s%s\n",
419                  channel->thread_id,
420                  (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
421                  (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
422                  (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
423
424       if (FD_ISSET (channel->fd, &read_fds))
425         channel->revents |= G_IO_IN;
426       if (FD_ISSET (channel->fd, &write_fds))
427         channel->revents |= G_IO_OUT;
428       if (FD_ISSET (channel->fd, &except_fds))
429         channel->revents |= G_IO_ERR;
430
431       if (channel->debug)
432         g_print ("select_thread %#x: resetting data_avail_noticed,\n"
433                  "\tsetting data_avail\n",
434                  channel->thread_id);
435       ResetEvent (channel->data_avail_noticed_event);
436       SetEvent (channel->data_avail_event);
437
438       if (channel->debug)
439         g_print ("select_thread %#x: waiting for data_avail_noticed\n",
440                  channel->thread_id);
441
442       WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
443       if (channel->debug)
444         g_print ("select_thread %#x: got data_avail_noticed\n",
445                  channel->thread_id);
446     }
447   
448   channel->running = FALSE;
449   LOCK (channel->mutex);
450   if (channel->needs_close)
451     {
452       if (channel->debug)
453         g_print ("select_thread %#x: channel fd %d needs closing\n",
454                  channel->thread_id, channel->fd);
455       closesocket (channel->fd);
456       channel->fd = -1;
457     }
458
459   if (channel->debug)
460     g_print ("select_thread %#x: got error, setting data_avail\n",
461              channel->thread_id);
462   SetEvent (channel->data_avail_event);
463   UNLOCK (channel->mutex);
464   
465   g_io_channel_unref((GIOChannel *)channel);
466   
467   /* No need to call _endthreadex(), the actual thread starter routine
468    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
469    * _endthreadex() for us.
470    */
471
472   CloseHandle (channel->thread_handle);
473
474   return 0;
475 }
476
477 static gboolean
478 g_io_win32_prepare (GSource *source,
479                     gint    *timeout)
480 {
481   GIOWin32Watch *watch = (GIOWin32Watch *)source;
482   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
483   
484   *timeout = -1;
485   
486   if (channel->type == G_IO_WIN32_FILE_DESC)
487     {
488       LOCK (channel->mutex);
489       if (channel->running && channel->wrp == channel->rdp)
490         channel->revents = 0;
491       UNLOCK (channel->mutex);
492     }
493   else if (channel->type == G_IO_WIN32_SOCKET)
494     {
495       channel->revents = 0;
496
497       if (channel->debug)
498         g_print ("g_io_win32_prepare: thread %#x, setting data_avail_noticed\n",
499                  channel->thread_id);
500       SetEvent (channel->data_avail_noticed_event);
501       if (channel->debug)
502         g_print ("g_io_win32_prepare: thread %#x, there.\n",
503                  channel->thread_id);
504     }
505
506   return FALSE;
507 }
508
509 static gboolean
510 g_io_win32_check (GSource *source)
511 {
512   GIOWin32Watch *watch = (GIOWin32Watch *)source;
513   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
514   
515   if (channel->debug)
516     g_print ("g_io_win32_check: for thread %#x:\n"
517              "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
518              channel->thread_id,
519              watch->pollfd.events, watch->pollfd.revents, channel->revents);
520
521   if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
522     watch->pollfd.revents = (watch->pollfd.events & channel->revents);
523
524   if (channel->type == G_IO_WIN32_SOCKET)
525     {
526       if (channel->debug)
527         g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
528                  channel->thread_id);
529       ResetEvent (channel->data_avail_event);
530       if (channel->debug)
531         g_print ("g_io_win32_check: thread %#x, there.\n",
532                  channel->thread_id);
533     }
534   
535   return (watch->pollfd.revents & watch->condition);
536 }
537
538 static gboolean
539 g_io_win32_dispatch (GSource     *source,
540                      GSourceFunc  callback,
541                      gpointer     user_data)
542 {
543   GIOFunc func = (GIOFunc)callback;
544   GIOWin32Watch *watch = (GIOWin32Watch *)source;
545   
546   if (!func)
547     {
548       g_warning ("GIOWin32Watch dispatched without callback\n"
549                  "You must call g_source_connect().");
550       return FALSE;
551     }
552   
553   return (*func) (watch->channel,
554                   watch->pollfd.revents & watch->condition,
555                   user_data);
556 }
557
558 static void
559 g_io_win32_destroy (GSource *source)
560 {
561   GIOWin32Watch *watch = (GIOWin32Watch *)source;
562   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
563   
564   if (channel->debug)
565     g_print ("g_io_win32_destroy: channel with thread %#x\n",
566              channel->thread_id);
567
568   channel->watches = g_slist_remove (channel->watches, watch);
569
570   g_io_channel_unref (watch->channel);
571 }
572
573 static GSourceFuncs win32_watch_funcs = {
574   g_io_win32_prepare,
575   g_io_win32_check,
576   g_io_win32_dispatch,
577   g_io_win32_destroy
578 };
579
580 static GSource *
581 g_io_win32_create_watch (GIOChannel    *channel,
582                          GIOCondition   condition,
583                          unsigned (__stdcall *thread) (void *parameter))
584 {
585   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
586   GIOWin32Watch *watch;
587   GSource *source;
588
589   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
590   watch = (GIOWin32Watch *)source;
591   
592   watch->channel = channel;
593   g_io_channel_ref (channel);
594   
595   watch->condition = condition;
596   
597   if (win32_channel->data_avail_event == NULL)
598     create_events (win32_channel);
599
600   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
601   watch->pollfd.events = condition;
602   
603   if (win32_channel->debug)
604     g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
605              win32_channel->fd, condition, watch->pollfd.fd);
606   
607   win32_channel->watches = g_slist_append (win32_channel->watches, watch);
608
609   if (win32_channel->thread_id == 0)
610     create_thread (win32_channel, condition, thread);
611
612   g_source_add_poll (source, &watch->pollfd);
613   
614   return source;
615 }
616
617 static GIOError
618 g_io_win32_msg_read (GIOChannel *channel,
619                      gchar      *buf,
620                      guint       count,
621                      guint      *bytes_read)
622 {
623   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
624   MSG msg;               /* In case of alignment problems */
625   
626   if (count < sizeof (MSG))
627     return G_IO_ERROR_INVAL;
628   
629   if (win32_channel->debug)
630     g_print ("g_io_win32_msg_read: for %#x\n",
631              win32_channel->hwnd);
632   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
633     return G_IO_ERROR_AGAIN;
634   
635   memmove (buf, &msg, sizeof (MSG));
636   *bytes_read = sizeof (MSG);
637   return G_IO_ERROR_NONE;
638 }
639
640 static GIOError
641 g_io_win32_msg_write (GIOChannel *channel,
642                       gchar      *buf,
643                       guint       count,
644                       guint      *bytes_written)
645 {
646   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
647   MSG msg;
648   
649   if (count != sizeof (MSG))
650     return G_IO_ERROR_INVAL;
651   
652   /* In case of alignment problems */
653   memmove (&msg, buf, sizeof (MSG));
654   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
655     return G_IO_ERROR_UNKNOWN;
656   
657   *bytes_written = sizeof (MSG);
658   return G_IO_ERROR_NONE;
659 }
660
661 static GIOError
662 g_io_win32_no_seek (GIOChannel *channel,
663                     gint        offset,
664                     GSeekType   type)
665 {
666   return G_IO_ERROR_UNKNOWN;
667 }
668
669 static void
670 g_io_win32_msg_close (GIOChannel *channel)
671 {
672   /* Nothing to be done. Or should we set hwnd to some invalid value? */
673 }
674
675 static void
676 g_io_win32_free (GIOChannel *channel)
677 {
678   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
679   
680   if (win32_channel->debug)
681     g_print ("thread %#x: freeing channel, fd: %d\n",
682              win32_channel->thread_id,
683              win32_channel->fd);
684
685   if (win32_channel->data_avail_event)
686     CloseHandle (win32_channel->data_avail_event);
687   if (win32_channel->space_avail_event)
688     CloseHandle (win32_channel->space_avail_event);
689   if (win32_channel->data_avail_noticed_event)
690     CloseHandle (win32_channel->data_avail_noticed_event);
691   DeleteCriticalSection (&win32_channel->mutex);
692
693   g_free (win32_channel->buffer);
694   g_slist_free (win32_channel->watches);
695   g_free (win32_channel);
696 }
697
698 static GSource *
699 g_io_win32_msg_create_watch (GIOChannel    *channel,
700                              GIOCondition   condition)
701 {
702   GIOWin32Watch *watch;
703   GSource *source;
704
705   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
706   watch = (GIOWin32Watch *)source;
707   
708   watch->channel = channel;
709   g_io_channel_ref (channel);
710   
711   watch->condition = condition;
712   
713   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
714   watch->pollfd.events = condition;
715   
716   g_source_add_poll (source, &watch->pollfd);
717   
718   return source;
719 }
720
721 static GIOError
722 g_io_win32_fd_read (GIOChannel *channel,
723                     gchar      *buf,
724                     guint       count,
725                     guint      *bytes_read)
726 {
727   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
728   gint result;
729   GIOError error;
730   
731   if (win32_channel->debug)
732     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
733              win32_channel->fd, count);
734   
735   if (win32_channel->thread_id)
736     {
737       result = buffer_read (win32_channel, buf, count, &error);
738       if (result < 0)
739         {
740           *bytes_read = 0;
741           return error;
742         }
743       else
744         {
745           *bytes_read = result;
746           return G_IO_ERROR_NONE;
747         }
748     }
749
750   result = read (win32_channel->fd, buf, count);
751
752   if (result < 0)
753     {
754       *bytes_read = 0;
755       if (errno == EINVAL)
756         return G_IO_ERROR_INVAL;
757       else
758         return G_IO_ERROR_UNKNOWN;
759     }
760   else
761     {
762       *bytes_read = result;
763       return G_IO_ERROR_NONE;
764     }
765 }
766
767 static GIOError
768 g_io_win32_fd_write (GIOChannel *channel,
769                      gchar      *buf,
770                      guint       count,
771                      guint      *bytes_written)
772 {
773   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
774   gint result;
775   
776   result = write (win32_channel->fd, buf, count);
777   if (win32_channel->debug)
778     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
779              win32_channel->fd, count, result);
780   
781   if (result < 0)
782     {
783       *bytes_written = 0;
784       switch (errno)
785         {
786         case EINVAL:
787           return G_IO_ERROR_INVAL;
788         case EAGAIN:
789           return G_IO_ERROR_AGAIN;
790         default:
791           return G_IO_ERROR_UNKNOWN;
792         }
793     }
794   else
795     {
796       *bytes_written = result;
797       return G_IO_ERROR_NONE;
798     }
799 }
800
801 static GIOError
802 g_io_win32_fd_seek (GIOChannel *channel,
803                     gint        offset,
804                     GSeekType   type)
805 {
806   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
807   int whence;
808   off_t result;
809   
810   switch (type)
811     {
812     case G_SEEK_SET:
813       whence = SEEK_SET;
814       break;
815     case G_SEEK_CUR:
816       whence = SEEK_CUR;
817       break;
818     case G_SEEK_END:
819       whence = SEEK_END;
820       break;
821     default:
822       g_warning ("g_io_win32_fd_seek: unknown seek type");
823       return G_IO_ERROR_UNKNOWN;
824     }
825   
826   result = lseek (win32_channel->fd, offset, whence);
827   
828   if (result < 0)
829     {
830       switch (errno)
831         {
832         case EINVAL:
833           return G_IO_ERROR_INVAL;
834         default:
835           return G_IO_ERROR_UNKNOWN;
836         }
837     }
838   else
839     return G_IO_ERROR_NONE;
840 }
841
842 static void
843 g_io_win32_fd_close (GIOChannel *channel)
844 {
845   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
846   
847   if (win32_channel->debug)
848     g_print ("thread %#x: closing fd %d\n",
849              win32_channel->thread_id,
850              win32_channel->fd);
851   LOCK (win32_channel->mutex);
852   if (win32_channel->running)
853     {
854       if (win32_channel->debug)
855         g_print ("thread %#x: running, marking fd %d for later close\n",
856                  win32_channel->thread_id, win32_channel->fd);
857       win32_channel->running = FALSE;
858       win32_channel->needs_close = TRUE;
859       SetEvent (win32_channel->data_avail_event);
860     }
861   else
862     {
863       if (win32_channel->debug)
864         g_print ("closing fd %d\n", win32_channel->fd);
865       close (win32_channel->fd);
866       if (win32_channel->debug)
867         g_print ("closed fd %d, setting to -1\n",
868                  win32_channel->fd);
869       win32_channel->fd = -1;
870     }
871   UNLOCK (win32_channel->mutex);
872 }
873
874 static GSource *
875 g_io_win32_fd_create_watch (GIOChannel    *channel,
876                             GIOCondition   condition)
877 {
878   return g_io_win32_create_watch (channel, condition, read_thread);
879 }
880
881 static GIOError
882 g_io_win32_sock_read (GIOChannel *channel,
883                       gchar      *buf,
884                       guint       count,
885                       guint      *bytes_read)
886 {
887   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
888   gint result;
889   GIOError error;
890
891   if (win32_channel->debug)
892     g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
893              win32_channel->fd, count);
894   
895   result = recv (win32_channel->fd, buf, count, 0);
896
897   if (win32_channel->debug)
898     g_print ("g_io_win32_sock_read: recv:%d\n", result);
899   
900   if (result == SOCKET_ERROR)
901     {
902       *bytes_read = 0;
903       switch (WSAGetLastError ())
904         {
905         case WSAEINVAL:
906           return G_IO_ERROR_INVAL;
907         case WSAEWOULDBLOCK:
908         case WSAEINTR:
909           return G_IO_ERROR_AGAIN;
910         default:
911           return G_IO_ERROR_UNKNOWN;
912         }
913     }
914   else
915     {
916       *bytes_read = result;
917       return G_IO_ERROR_NONE;
918     }
919 }
920
921 static GIOError
922 g_io_win32_sock_write (GIOChannel *channel,
923                        gchar      *buf,
924                        guint       count,
925                        guint      *bytes_written)
926 {
927   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
928   gint result;
929   
930   if (win32_channel->debug)
931     g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
932              win32_channel->fd, count);
933   
934   result = send (win32_channel->fd, buf, count, 0);
935   
936   if (win32_channel->debug)
937     g_print ("g_io_win32_sock_write: send:%d\n", result);
938   
939   if (result == SOCKET_ERROR)
940     {
941       *bytes_written = 0;
942       switch (WSAGetLastError ())
943         {
944         case WSAEINVAL:
945           return G_IO_ERROR_INVAL;
946         case WSAEWOULDBLOCK:
947         case WSAEINTR:
948           return G_IO_ERROR_AGAIN;
949         default:
950           return G_IO_ERROR_UNKNOWN;
951         }
952     }
953   else
954     {
955       *bytes_written = result;
956       return G_IO_ERROR_NONE;
957     }
958 }
959
960 static void
961 g_io_win32_sock_close (GIOChannel *channel)
962 {
963   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
964
965   if (win32_channel->debug)
966     g_print ("thread %#x: closing socket %d\n",
967              win32_channel->thread_id,
968              win32_channel->fd);
969   closesocket (win32_channel->fd);
970   win32_channel->fd = -1;
971 }
972
973 static GSource *
974 g_io_win32_sock_create_watch (GIOChannel    *channel,
975                               GIOCondition   condition)
976 {
977   return g_io_win32_create_watch (channel, condition, select_thread);
978 }
979
980 static GIOFuncs win32_channel_msg_funcs = {
981   g_io_win32_msg_read,
982   g_io_win32_msg_write,
983   g_io_win32_no_seek,
984   g_io_win32_msg_close,
985   g_io_win32_msg_create_watch,
986   g_io_win32_free
987 };
988
989 static GIOFuncs win32_channel_fd_funcs = {
990   g_io_win32_fd_read,
991   g_io_win32_fd_write,
992   g_io_win32_fd_seek,
993   g_io_win32_fd_close,
994   g_io_win32_fd_create_watch,
995   g_io_win32_free
996 };
997
998 static GIOFuncs win32_channel_sock_funcs = {
999   g_io_win32_sock_read,
1000   g_io_win32_sock_write,
1001   g_io_win32_no_seek,
1002   g_io_win32_sock_close,
1003   g_io_win32_sock_create_watch,
1004   g_io_win32_free
1005 };
1006
1007 GIOChannel *
1008 g_io_channel_win32_new_messages (guint hwnd)
1009 {
1010   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1011   GIOChannel *channel = (GIOChannel *)win32_channel;
1012
1013   g_io_channel_init (channel);
1014   g_io_channel_win32_init (win32_channel);
1015   if (win32_channel->debug)
1016     g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
1017   channel->funcs = &win32_channel_msg_funcs;
1018   win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1019   win32_channel->hwnd = (HWND) hwnd;
1020
1021   return channel;
1022 }
1023
1024 GIOChannel *
1025 g_io_channel_win32_new_fd (gint fd)
1026 {
1027   GIOWin32Channel *win32_channel;
1028   GIOChannel *channel;
1029   struct stat st;
1030
1031   if (fstat (fd, &st) == -1)
1032     {
1033       g_warning ("%d isn't a (emulated) file descriptor", fd);
1034       return NULL;
1035     }
1036
1037   win32_channel = g_new (GIOWin32Channel, 1);
1038   channel = (GIOChannel *)win32_channel;
1039
1040   g_io_channel_init (channel);
1041   g_io_channel_win32_init (win32_channel);
1042   if (win32_channel->debug)
1043     g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
1044   channel->funcs = &win32_channel_fd_funcs;
1045   win32_channel->type = G_IO_WIN32_FILE_DESC;
1046   win32_channel->fd = fd;
1047
1048   return channel;
1049 }
1050
1051 gint
1052 g_io_channel_win32_get_fd (GIOChannel *channel)
1053 {
1054   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1055
1056   return win32_channel->fd;
1057 }
1058
1059 GIOChannel *
1060 g_io_channel_win32_new_socket (int socket)
1061 {
1062   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1063   GIOChannel *channel = (GIOChannel *)win32_channel;
1064
1065   g_io_channel_init (channel);
1066   g_io_channel_win32_init (win32_channel);
1067   if (win32_channel->debug)
1068     g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
1069   channel->funcs = &win32_channel_sock_funcs;
1070   win32_channel->type = G_IO_WIN32_SOCKET;
1071   win32_channel->fd = socket;
1072
1073   return channel;
1074 }
1075
1076 GIOChannel *
1077 g_io_channel_unix_new (gint fd)
1078 {
1079   struct stat st;
1080
1081   if (fstat (fd, &st) == 0)
1082     return g_io_channel_win32_new_fd (fd);
1083   
1084   if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
1085     return g_io_channel_win32_new_socket(fd);
1086
1087   g_warning ("%d is neither a file descriptor or a socket", fd);
1088   return NULL;
1089 }
1090
1091 gint
1092 g_io_channel_unix_get_fd (GIOChannel *channel)
1093 {
1094   return g_io_channel_win32_get_fd (channel);
1095 }
1096
1097 void
1098 g_io_channel_win32_set_debug (GIOChannel *channel,
1099                               gboolean    flag)
1100 {
1101   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1102
1103   win32_channel->debug = flag;
1104 }
1105
1106 gint
1107 g_io_channel_win32_poll (GPollFD *fds,
1108                          gint     n_fds,
1109                          gint     timeout)
1110 {
1111   int result;
1112
1113   g_return_val_if_fail (n_fds >= 0, 0);
1114
1115   result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1116
1117   return result;
1118 }
1119
1120 void
1121 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
1122                                 GIOCondition  condition,
1123                                 GPollFD      *fd)
1124 {
1125   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1126
1127   if (win32_channel->data_avail_event == NULL)
1128     create_events (win32_channel);
1129   
1130   fd->fd = (gint) win32_channel->data_avail_event;
1131   fd->events = condition;
1132
1133   if (win32_channel->thread_id == 0)
1134     if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
1135       create_thread (win32_channel, condition, read_thread);
1136     else if (win32_channel->type == G_IO_WIN32_SOCKET)
1137       create_thread (win32_channel, condition, select_thread);
1138 }
1139
1140 /* Binary compatibility */
1141 GIOChannel *
1142 g_io_channel_win32_new_stream_socket (int socket)
1143 {
1144   return g_io_channel_win32_new_socket (socket);
1145 }