giowin32.c 45.5 KB
Newer Older
1 2 3 4 5
/* GLIB - Library of useful routines for C programming
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * giowin32.c: IO Channels for Win32.
 * Copyright 1998 Owen Taylor and Tor Lillqvist
6
 * Copyright 1999-2000 Tor Lillqvist and Craig Setera
7
 * Copyright 2001-2003 Andrew Lanoix
8 9
 *
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11 12 13 14 15
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20 21 22 23 24
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

25
/*
26
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
27 28
 * file for a list of people on the GLib Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
29
 * GLib at ftp://ftp.gtk.org/pub/gtk/.
30 31
 */

32
/* Define this to get (very) verbose logging of all channels */
33
/* #define G_IO_WIN32_DEBUG */
34

Owen Taylor's avatar
Owen Taylor committed
35 36
#include "config.h"

37
#include "galias.h"
38
#include "glib.h"
39 40

#include <stdlib.h>
41
#include <windows.h>
42
#include <winsock.h>          /* Not everybody has winsock2 */
43 44
#include <fcntl.h>
#include <io.h>
45
#include <process.h>
46
#include <errno.h>
47
#include <sys/stat.h>
48

49
#include "gstdio.h"
50 51
#include "glibintl.h"

52 53 54
typedef struct _GIOWin32Channel GIOWin32Channel;
typedef struct _GIOWin32Watch GIOWin32Watch;

55
#define BUFFER_SIZE 4096
56 57

typedef enum {
58 59
  G_IO_WIN32_WINDOWS_MESSAGES,	/* Windows messages */
  G_IO_WIN32_FILE_DESC,		/* Unix-like file descriptors from
60 61 62
				 * _open() or _pipe(). Read with read().
				 * Have to create separate thread to read.
				 */
63 64
  G_IO_WIN32_SOCKET		/* Sockets. A separate thread is blocked
				 * in select() most of the time.
65
				 */
66 67 68 69 70 71 72 73 74
} GIOWin32ChannelType;

struct _GIOWin32Channel {
  GIOChannel channel;
  gint fd;			/* Either a Unix-like file handle as provided
				 * by the Microsoft C runtime, or a SOCKET
				 * as provided by WinSock.
				 */
  GIOWin32ChannelType type;
75
  
76 77
  gboolean debug;

78 79 80
  CRITICAL_SECTION mutex;

  /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
81
  HWND hwnd;			/* handle of window, or NULL */
82
  
83 84 85 86 87 88 89 90 91 92 93 94 95 96
  /* Following fields are used by both fd and socket channels. */
  gboolean running;		/* Is reader thread running. FALSE if
				 * EOF has been reached.
				 */
  gboolean needs_close;		/* If the channel has been closed while
				 * the reader thread was still running.
				 */
  guint thread_id;		/* If non-NULL has a reader thread, or has
				 * had.*/
  HANDLE data_avail_event;

  gushort revents;

  /* Following fields used by fd channels for input */
97 98 99 100 101 102 103 104 105 106 107 108 109 110
  
  /* Data is kept in a circular buffer. To be able to distinguish between
   * empty and full buffer, we cannot fill it completely, but have to
   * leave a one character gap.
   *
   * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
   *
   * Empty:    wrp == rdp
   * Full:     (wrp + 1) % BUFFER_SIZE == rdp
   * Partial:  otherwise
   */
  guchar *buffer;		/* (Circular) buffer */
  gint wrp, rdp;		/* Buffer indices for writing and reading */
  HANDLE space_avail_event;
111 112 113 114

  /* Following fields used by socket channels */
  GSList *watches;
  HANDLE data_avail_noticed_event;
115 116
  gint reset_send; /* socket used to send data so select_thread() can reset/re-loop */
  gint reset_recv; /* socket used to recv data so select_thread() can reset/re-loop */
117 118
};

119 120 121
#define LOCK(mutex) EnterCriticalSection (&mutex)
#define UNLOCK(mutex) LeaveCriticalSection (&mutex)

122
struct _GIOWin32Watch {
123
  GSource       source;
124 125 126 127 128
  GPollFD       pollfd;
  GIOChannel   *channel;
  GIOCondition  condition;
};

129
static void
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
g_win32_print_access_mode (int flags)
{
  g_print ("%s%s%s%s%s%s%s%s%s%s",
	   ((flags & 0x3) == _O_RDWR ? "O_RDWR" :
	    ((flags & 0x3) == _O_RDONLY ? "O_RDONLY" :
	     ((flags & 0x3) == _O_WRONLY ? "O_WRONLY" : "0"))),
	   (flags & _O_APPEND ? "|O_APPEND" : ""),
	   (flags & _O_RANDOM ? "|O_RANDOM" : ""),
	   (flags & _O_SEQUENTIAL ? "|O_SEQUENTIAL" : ""),
	   (flags & _O_TEMPORARY ? "|O_TEMPORARY" : ""),
	   (flags & _O_CREAT ? "|O_CREAT" : ""),
	   (flags & _O_TRUNC ? "|O_TRUNC" : ""),
	   (flags & _O_EXCL ? "|O_EXCL" : ""),
	   (flags & _O_TEXT ? "|O_TEXT" : ""),
	   (flags & _O_BINARY ? "|O_BINARY" : ""));
}

static void
g_win32_print_gioflags (GIOFlags flags)
{
  char *bar = "";

  if (flags & G_IO_FLAG_APPEND)
    bar = "|", g_print ("APPEND");
  if (flags & G_IO_FLAG_NONBLOCK)
    g_print ("%sNONBLOCK", bar), bar = "|";
  if (flags & G_IO_FLAG_IS_READABLE)
    g_print ("%sREADABLE", bar), bar = "|";
  if (flags & G_IO_FLAG_IS_WRITEABLE)
    g_print ("%sWRITEABLE", bar), bar = "|";
  if (flags & G_IO_FLAG_IS_SEEKABLE)
    g_print ("%sSEEKABLE", bar), bar = "|";
}

static gboolean
g_io_win32_get_debug_flag (void)
166 167
{
#ifdef G_IO_WIN32_DEBUG
168
  return TRUE;
169 170
#else
  if (getenv ("G_IO_WIN32_DEBUG") != NULL)
171
    return TRUE;
172
  else
173
    return FALSE;
174
#endif
175 176 177 178 179 180
}  

static void
g_io_channel_win32_init (GIOWin32Channel *channel)
{
  channel->debug = g_io_win32_get_debug_flag ();
181 182
  channel->buffer = NULL;
  channel->running = FALSE;
183
  channel->needs_close = FALSE;
184
  channel->thread_id = 0;
185
  channel->data_avail_event = NULL;
186
  channel->revents = 0;
187
  channel->space_avail_event = NULL;
188 189
  channel->reset_send = INVALID_SOCKET;
  channel->reset_recv = INVALID_SOCKET;
190 191
  channel->data_avail_noticed_event = NULL;
  channel->watches = NULL;
192
  InitializeCriticalSection (&channel->mutex);
193 194
}

195 196 197 198 199
static void
create_events (GIOWin32Channel *channel)
{
  SECURITY_ATTRIBUTES sec_attrs;
  
200
  sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
201 202
  sec_attrs.lpSecurityDescriptor = NULL;
  sec_attrs.bInheritHandle = FALSE;
203

204 205 206 207
  /* The data available event is manual reset, the space available event
   * is automatic reset.
   */
  if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
208 209
      || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
      || !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
210
    {
211 212 213
      gchar *emsg = g_win32_error_message (GetLastError ());
      g_error ("Error creating event: %s", emsg);
      g_free (emsg);
214 215
    }
}
216

217
static unsigned __stdcall
218
read_thread (void *parameter)
219 220 221 222
{
  GIOWin32Channel *channel = parameter;
  guchar *buffer;
  guint nbytes;
223

224
  g_io_channel_ref ((GIOChannel *)channel);
225

226
  if (channel->debug)
227
    g_print ("read_thread %#x: start fd:%d, data_avail:%#x space_avail:%#x\n",
228 229 230 231
	     channel->thread_id,
	     channel->fd,
	     (guint) channel->data_avail_event,
	     (guint) channel->space_avail_event);
232 233 234 235
  
  channel->buffer = g_malloc (BUFFER_SIZE);
  channel->rdp = channel->wrp = 0;
  channel->running = TRUE;
236

237 238
  SetEvent (channel->space_avail_event);
  
239
  LOCK (channel->mutex);
240 241
  while (channel->running)
    {
242
      if (channel->debug)
243
	g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
244
		 channel->thread_id, channel->rdp, channel->wrp);
245 246 247
      if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
	{
	  /* Buffer is full */
248
	  if (channel->debug)
249
	    g_print ("read_thread %#x: resetting space_avail\n",
250
		     channel->thread_id);
251
	  ResetEvent (channel->space_avail_event);
252
	  if (channel->debug)
253 254
	    g_print ("read_thread %#x: waiting for space\n",
		     channel->thread_id);
255 256 257
	  UNLOCK (channel->mutex);
	  WaitForSingleObject (channel->space_avail_event, INFINITE);
	  LOCK (channel->mutex);
258
	  if (channel->debug)
259
	    g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
260
		     channel->thread_id, channel->rdp, channel->wrp);
261 262 263 264 265 266 267 268 269
	}
      
      buffer = channel->buffer + channel->wrp;
      
      /* Always leave at least one byte unused gap to be able to
       * distinguish between the full and empty condition...
       */
      nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
		    BUFFER_SIZE - channel->wrp);
270

271
      if (channel->debug)
272
	g_print ("read_thread %#x: calling read() for %d bytes\n",
273 274
		 channel->thread_id, nbytes);

275
      UNLOCK (channel->mutex);
276

277
      nbytes = read (channel->fd, buffer, nbytes);
278 279
      
      LOCK (channel->mutex);
280

281 282 283 284 285 286
      channel->revents = G_IO_IN;
      if (nbytes == 0)
	channel->revents |= G_IO_HUP;
      else if (nbytes < 0)
	channel->revents |= G_IO_ERR;

287
      if (channel->debug)
288
	g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
289
		 channel->thread_id, nbytes, channel->rdp, channel->wrp);
290 291 292 293

      if (nbytes <= 0)
	break;

294
      channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
295
      if (channel->debug)
296
	g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
297
		 channel->thread_id, channel->rdp, channel->wrp);
298 299 300 301
      SetEvent (channel->data_avail_event);
    }
  
  channel->running = FALSE;
302 303 304
  if (channel->needs_close)
    {
      if (channel->debug)
305
	g_print ("read_thread %#x: channel fd %d needs closing\n",
306
		 channel->thread_id, channel->fd);
307
      close (channel->fd);
308 309 310
      channel->fd = -1;
    }

311 312 313
  if (channel->debug)
    g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
	     channel->thread_id, channel->rdp, channel->wrp);
314 315 316
  SetEvent (channel->data_avail_event);
  UNLOCK (channel->mutex);
  
317
  g_io_channel_unref ((GIOChannel *)channel);
318
  
319 320 321
  /* No need to call _endthreadex(), the actual thread starter routine
   * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
   * _endthreadex() for us.
322
   */
323

324 325
  return 0;
}
326

327
static void
328 329 330
create_thread (GIOWin32Channel     *channel,
	       GIOCondition         condition,
	       unsigned (__stdcall *thread) (void *parameter))
331
{
332 333 334 335 336
  HANDLE thread_handle;

  thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
					   &channel->thread_id);
  if (thread_handle == 0)
337
    g_warning (G_STRLOC ": Error creating reader thread: %s",
Owen Taylor's avatar
Owen Taylor committed
338
	       g_strerror (errno));
339 340 341 342
  else if (!CloseHandle (thread_handle))
    g_warning (G_STRLOC ": Error closing thread handle: %s\n",
	       g_win32_error_message (GetLastError ()));

343 344
  WaitForSingleObject (channel->space_avail_event, INFINITE);
}
345

346
static void
347
init_reset_sockets (GIOWin32Channel *channel)
348 349 350 351
{
  struct sockaddr_in local, local2, server;
  int len;

352
  channel->reset_send = (gint) socket (AF_INET, SOCK_DGRAM, 0);
353
  if (channel->reset_send == INVALID_SOCKET)
354 355 356 357
    {
      g_warning (G_STRLOC ": Error creating reset_send socket: %s\n",
		 g_win32_error_message (WSAGetLastError ()));
    }
358 359 360

  local.sin_family = AF_INET;
  local.sin_port = 0;
361
  local.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
362

363 364 365 366
  if (bind (channel->reset_send, (struct sockaddr *)&local, sizeof (local)) == SOCKET_ERROR)
    {
      g_warning (G_STRLOC ": Error binding to reset_send socket: %s\n",
		 g_win32_error_message (WSAGetLastError ()));
367 368 369 370
  }

  local2.sin_family = AF_INET;
  local2.sin_port = 0;
371
  local2.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
372

373
  channel->reset_recv = (gint) socket (AF_INET, SOCK_DGRAM, 0);
374
  if (channel->reset_recv == INVALID_SOCKET)
375 376 377
    {
      g_warning (G_STRLOC ": Error creating reset_recv socket: %s\n",
		 g_win32_error_message (WSAGetLastError ()));
378 379
  }

380 381 382 383 384
  if (bind (channel->reset_recv, (struct sockaddr *)&local2, sizeof (local)) == SOCKET_ERROR)
    {
      g_warning (G_STRLOC ": Error binding to reset_recv socket: %s\n",
		 g_win32_error_message (WSAGetLastError ()));
    }
385
  
386 387 388 389 390 391
  len = sizeof (local2);
  if (getsockname (channel->reset_recv, (struct sockaddr *)&local2, &len) == SOCKET_ERROR)
    {
      g_warning (G_STRLOC ": Error getsockname with reset_recv socket: %s\n",
		 g_win32_error_message (WSAGetLastError ()));
    }
392

393 394 395
  memset (&server, 0, sizeof (server));
  server.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
  server.sin_family = AF_INET;
396 397
  server.sin_port = local2.sin_port;

398 399 400 401
  if (connect (channel->reset_send, (struct sockaddr  *)&server, sizeof (server)) == SOCKET_ERROR)
    {
      g_warning (G_STRLOC ": connect to reset_recv socket: %s\n",
		 g_win32_error_message (WSAGetLastError ()));
402 403 404 405
  }

}

406
static GIOStatus
407 408
buffer_read (GIOWin32Channel *channel,
	     guchar          *dest,
409 410 411
	     gsize            count,
	     gsize           *bytes_read,
	     GError         **err)
412
{
413 414 415 416
  guint nbytes;
  guint left = count;
  
  LOCK (channel->mutex);
417 418 419
  if (channel->debug)
    g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
	     channel->thread_id, count, channel->rdp, channel->wrp);
420
  
421
  if (channel->wrp == channel->rdp)
422 423
    {
      UNLOCK (channel->mutex);
424 425 426
      if (channel->debug)
	g_print ("waiting for data from thread %#x\n", channel->thread_id);
      WaitForSingleObject (channel->data_avail_event, INFINITE);
427 428
      if (channel->debug)
	g_print ("done waiting for data from thread %#x\n", channel->thread_id);
429
      LOCK (channel->mutex);
430
      if (channel->wrp == channel->rdp && !channel->running)
431
	{
432 433
	  if (channel->debug)
	    g_print ("wrp==rdp, !running\n");
434
	  UNLOCK (channel->mutex);
435
          *bytes_read = 0;
436
	  return G_IO_STATUS_EOF;
437
	}
438
    }
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
  
  if (channel->rdp < channel->wrp)
    nbytes = channel->wrp - channel->rdp;
  else
    nbytes = BUFFER_SIZE - channel->rdp;
  UNLOCK (channel->mutex);
  nbytes = MIN (left, nbytes);
  if (channel->debug)
    g_print ("moving %d bytes from thread %#x\n",
	     nbytes, channel->thread_id);
  memcpy (dest, channel->buffer + channel->rdp, nbytes);
  dest += nbytes;
  left -= nbytes;
  LOCK (channel->mutex);
  channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
  if (channel->debug)
455
    g_print ("setting space_avail for thread %#x\n", channel->thread_id);
456 457 458 459
  SetEvent (channel->space_avail_event);
  if (channel->debug)
    g_print ("for thread %#x: rdp=%d, wrp=%d\n",
	     channel->thread_id, channel->rdp, channel->wrp);
460
  if (channel->running && channel->wrp == channel->rdp)
461 462
    {
      if (channel->debug)
463
	g_print ("resetting data_avail of thread %#x\n",
464 465 466
		 channel->thread_id);
      ResetEvent (channel->data_avail_event);
    };
467 468
  UNLOCK (channel->mutex);
  
469 470 471
  /* We have no way to indicate any errors form the actual
   * read() or recv() call in the reader thread. Should we have?
   */
472 473
  *bytes_read = count - left;
  return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
474
}
475

476 477 478 479 480 481 482
static unsigned __stdcall
select_thread (void *parameter)
{
  GIOWin32Channel *channel = parameter;
  fd_set read_fds, write_fds, except_fds;
  GSList *tmp;
  int n;
483
  char buffer[8];
484 485 486 487

  g_io_channel_ref ((GIOChannel *)channel);

  if (channel->debug)
488
    g_print ("select_thread %#x: start fd:%d data_avail:%#x data_avail_noticed:%#x\n",
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
	     channel->thread_id,
	     channel->fd,
	     (guint) channel->data_avail_event,
	     (guint) channel->data_avail_noticed_event);
  
  channel->rdp = channel->wrp = 0;
  channel->running = TRUE;

  SetEvent (channel->space_avail_event);
  
  while (channel->running)
    {
      FD_ZERO (&read_fds);
      FD_ZERO (&write_fds);
      FD_ZERO (&except_fds);
504
      FD_SET (channel->reset_recv, &read_fds);
505

506
      LOCK (channel->mutex);
507 508
      tmp = channel->watches;
      while (tmp)
509 510 511 512 513 514 515 516 517
	{
	  GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;

	  if (watch->condition & (G_IO_IN | G_IO_HUP))
	    FD_SET (channel->fd, &read_fds);
	  if (watch->condition & G_IO_OUT)
	    FD_SET (channel->fd, &write_fds);
	  if (watch->condition & G_IO_ERR)
	    FD_SET (channel->fd, &except_fds);
518
	  
519 520
	  tmp = tmp->next;
	}
521 522
      UNLOCK (channel->mutex);

523
      if (channel->debug)
524 525 526 527 528 529
	g_print ("select_thread %#x: calling select() for%s%s%s\n",
		 channel->thread_id,
		 (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
		 (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
		 (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
      
530 531
      n = select (1, &read_fds, &write_fds, &except_fds, NULL);
      
532
      LOCK (channel->mutex);
533
      if (channel->needs_close)
534 535 536 537
	{
	  UNLOCK (channel->mutex);
	  break;
	}
538 539
      UNLOCK (channel->mutex);

540 541 542 543 544 545 546 547
      if (n == SOCKET_ERROR)
	{
	  if (channel->debug)
	    g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
		     channel->thread_id);
	  break;
	}

548
    if (FD_ISSET (channel->reset_recv, &read_fds))
549
    {
550
      if (channel->debug)
551 552
        g_print ("select_thread %#x: re-looping\n",
            channel->thread_id);
553
      recv (channel->reset_recv,  (char *)&buffer, (int) sizeof (buffer), 0);
554 555
      continue;
    }
556

557
    if (channel->debug)
558 559 560 561 562 563
      g_print ("select_thread %#x: got%s%s%s\n",
	       channel->thread_id,
	       (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
	       (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
	       (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
    
564 565 566 567 568 569 570 571 572
    if (FD_ISSET (channel->fd, &read_fds))
      channel->revents |= G_IO_IN;
    if (FD_ISSET (channel->fd, &write_fds))
      channel->revents |= G_IO_OUT;
    if (FD_ISSET (channel->fd, &except_fds))
      channel->revents |= G_IO_ERR;

    if (channel->debug)
      g_print ("select_thread %#x: resetting data_avail_noticed, setting data_avail\n",
573
	       channel->thread_id);
574 575 576 577 578

    LOCK (channel->mutex);
    ResetEvent (channel->data_avail_noticed_event);
    SetEvent (channel->data_avail_event);
    if (channel->needs_close)
579 580 581 582
      {
	UNLOCK (channel->mutex);
	break;
      }
583
    UNLOCK (channel->mutex);
584

585 586 587
    if (channel->debug)
      g_print ("select_thread %#x: waiting for data_avail_noticed\n",
        channel->thread_id);
588

589 590 591
    WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
    if (channel->debug)
      g_print ("select_thread %#x: got data_avail_noticed\n",
592 593 594
		 channel->thread_id);
    }

595 596
  LOCK (channel->mutex);
  channel->running = FALSE;
597 598 599 600
  if (channel->debug)
    g_print ("select_thread %#x: got error, setting data_avail\n",
	     channel->thread_id);
  SetEvent (channel->data_avail_event);
601
  g_io_channel_unref ((GIOChannel *)channel);
602 603
  UNLOCK (channel->mutex);

604 605 606 607 608 609 610 611
  /* No need to call _endthreadex(), the actual thread starter routine
   * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
   * _endthreadex() for us.
   */

  return 0;
}

612
static gboolean
613 614
g_io_win32_prepare (GSource *source,
		    gint    *timeout)
615
{
616
  GIOWin32Watch *watch = (GIOWin32Watch *)source;
617
  GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
618 619
  GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
  
620
  *timeout = -1;
621
  
622 623 624 625 626 627
  if (channel->debug)
    g_print ("g_io_win32_prepare: for thread %#x buffer_condition:%#x\n"
	     "  watch->pollfd.events:%#x watch->pollfd.revents:%#x channel->revents:%#x\n",
	     channel->thread_id, buffer_condition,
	     watch->pollfd.events, watch->pollfd.revents, channel->revents);

628 629 630 631
  if (channel->type == G_IO_WIN32_FILE_DESC)
    {
      LOCK (channel->mutex);
      if (channel->running && channel->wrp == channel->rdp)
632 633 634 635 636 637
	{
	  if (channel->debug)
	    g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
		     channel->thread_id);
	  channel->revents = 0;
	}
638 639 640 641
      UNLOCK (channel->mutex);
    }
  else if (channel->type == G_IO_WIN32_SOCKET)
    {
642
      LOCK (channel->mutex);
643 644
      channel->revents = 0;
      if (channel->debug)
645
	g_print ("g_io_win32_prepare: for thread %#x, setting data_avail_noticed\n",
646 647 648 649 650
		 channel->thread_id);
      SetEvent (channel->data_avail_noticed_event);
      if (channel->debug)
	g_print ("g_io_win32_prepare: thread %#x, there.\n",
		 channel->thread_id);
651
      UNLOCK (channel->mutex);
652 653
    }

654
  return ((watch->condition & buffer_condition) == watch->condition);
655 656
}

657
static gboolean
658
g_io_win32_check (GSource *source)
659
{
660
  MSG msg;
661
  GIOWin32Watch *watch = (GIOWin32Watch *)source;
662
  GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
663 664
  GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);

665
  if (channel->debug)
666 667 668
    g_print ("g_io_win32_check: for thread %#x buffer_condition:%#x\n"
	     "  watch->pollfd.events:%#x watch->pollfd.revents:%#x channel->revents:%#x\n",
	     channel->thread_id, buffer_condition,
669 670 671
	     watch->pollfd.events, watch->pollfd.revents, channel->revents);

  if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
672 673 674 675 676 677 678 679
    {
      watch->pollfd.revents = (watch->pollfd.events & channel->revents);
    }
  else
    {
      return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
    }
  
680
  if (channel->type == G_IO_WIN32_SOCKET)
681
    {
682
      LOCK (channel->mutex);
683
      if (channel->debug)
684 685 686 687 688 689
	g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
		 channel->thread_id);
      ResetEvent (channel->data_avail_event);
      if (channel->debug)
	g_print ("g_io_win32_check: thread %#x, there.\n",
		 channel->thread_id);
690
      UNLOCK (channel->mutex);
691
    }
692

693
  return ((watch->pollfd.revents | buffer_condition) & watch->condition);
694 695 696
}

static gboolean
697 698 699
g_io_win32_dispatch (GSource     *source,
		     GSourceFunc  callback,
		     gpointer     user_data)
700
{
701
  GIOFunc func = (GIOFunc)callback;
702
  GIOWin32Watch *watch = (GIOWin32Watch *)source;
703
  GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
704
  
705 706
  if (!func)
    {
707
      g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
708 709 710 711 712
		 "You must call g_source_connect().");
      return FALSE;
    }
  
  return (*func) (watch->channel,
713
		  (watch->pollfd.revents | buffer_condition) & watch->condition,
714
		  user_data);
715 716 717
}

static void
718
g_io_win32_finalize (GSource *source)
719
{
720
  GIOWin32Watch *watch = (GIOWin32Watch *)source;
721
  GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
722
  char send_buffer[] = "f";
723
  
724
  LOCK (channel->mutex);
725
  if (channel->debug)
726
    g_print ("g_io_win32_finalize: channel with thread %#x\n",
727 728 729 730
	     channel->thread_id);

  channel->watches = g_slist_remove (channel->watches, watch);

731
  SetEvent (channel->data_avail_noticed_event);
732
  if (channel->type == G_IO_WIN32_SOCKET)
733 734 735 736
  {
    /* Tell select_thread() to exit */
    channel->needs_close = 1;
    /* Wake up select_thread() from its blocking select() */
737
    send (channel->reset_send, send_buffer, sizeof (send_buffer), 0);
738
  }
739

740
  g_io_channel_unref (watch->channel);
741
  UNLOCK (channel->mutex);
742 743
}

744
GSourceFuncs g_io_watch_funcs = {
745 746 747
  g_io_win32_prepare,
  g_io_win32_check,
  g_io_win32_dispatch,
748
  g_io_win32_finalize
749
};
750

751 752 753
static GSource *
g_io_win32_create_watch (GIOChannel    *channel,
			 GIOCondition   condition,
754
			 unsigned (__stdcall *thread) (void *parameter))
755
{
756
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
757 758
  GIOWin32Watch *watch;
  GSource *source;
759
  char send_buffer[] = "c";
760

761
  source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
762
  watch = (GIOWin32Watch *)source;
763 764 765 766 767 768 769 770 771 772 773 774 775
  
  watch->channel = channel;
  g_io_channel_ref (channel);
  
  watch->condition = condition;
  
  if (win32_channel->data_avail_event == NULL)
    create_events (win32_channel);

  watch->pollfd.fd = (gint) win32_channel->data_avail_event;
  watch->pollfd.events = condition;
  
  if (win32_channel->debug)
776 777
    g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
	     win32_channel->fd, condition, watch->pollfd.fd);
778 779

  LOCK (win32_channel->mutex);
780 781
  win32_channel->watches = g_slist_append (win32_channel->watches, watch);

782
  if (win32_channel->thread_id == 0)
783
    create_thread (win32_channel, condition, thread);
784
  else
785
    send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0);
786

787
  g_source_add_poll (source, &watch->pollfd);
788 789
  UNLOCK (win32_channel->mutex);

790
  return source;
791 792
}

793
static GIOStatus
794 795
g_io_win32_msg_read (GIOChannel *channel,
		     gchar      *buf,
796 797 798
		     gsize       count,
		     gsize      *bytes_read,
		     GError    **err)
799
{
800
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
801 802
  MSG msg;               /* In case of alignment problems */
  
803
  if (count < sizeof (MSG))
804
    {
805 806
      g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
		   "Incorrect message size"); /* Informative enough error message? */
807 808
      return G_IO_STATUS_ERROR;
    }
809
  
810 811
  if (win32_channel->debug)
    g_print ("g_io_win32_msg_read: for %#x\n",
812
	     (guint) win32_channel->hwnd);
813
  if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
814
    return G_IO_STATUS_AGAIN;
815

816 817
  memmove (buf, &msg, sizeof (MSG));
  *bytes_read = sizeof (MSG);
818

819
  return G_IO_STATUS_NORMAL;
820
}
821

822 823 824 825 826 827
static GIOStatus
g_io_win32_msg_write (GIOChannel  *channel,
		      const gchar *buf,
		      gsize        count,
		      gsize       *bytes_written,
		      GError     **err)
828
{
829
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
830
  MSG msg;
831
  
832
  if (count != sizeof (MSG))
833
    {
834 835
      g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
		   "Incorrect message size"); /* Informative enough error message? */
836 837
      return G_IO_STATUS_ERROR;
    }
838
  
839 840 841
  /* In case of alignment problems */
  memmove (&msg, buf, sizeof (MSG));
  if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
842
    {
843
      gchar *emsg = g_win32_error_message (GetLastError ());
844
      g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
845
      g_free (emsg);
846 847 848
      return G_IO_STATUS_ERROR;
    }

849
  *bytes_written = sizeof (MSG);
850 851

  return G_IO_STATUS_NORMAL;
852 853
}

854 855 856
static GIOStatus
g_io_win32_msg_close (GIOChannel *channel,
		      GError    **err)
857 858
{
  /* Nothing to be done. Or should we set hwnd to some invalid value? */
859 860

  return G_IO_STATUS_NORMAL;
861 862
}

863
static void
864 865
g_io_win32_free (GIOChannel *channel)
{
866
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
867
  
868 869 870 871 872
  if (win32_channel->debug)
    g_print ("thread %#x: freeing channel, fd: %d\n",
	     win32_channel->thread_id,
	     win32_channel->fd);

873
  if (win32_channel->reset_send && win32_channel->reset_send != INVALID_SOCKET)
874
    closesocket (win32_channel->reset_send);
875
  if (win32_channel->reset_recv && win32_channel->reset_recv != INVALID_SOCKET)
876
    closesocket (win32_channel->reset_recv);
877 878 879 880 881 882 883
  if (win32_channel->data_avail_event)
    CloseHandle (win32_channel->data_avail_event);
  if (win32_channel->space_avail_event)
    CloseHandle (win32_channel->space_avail_event);
  if (win32_channel->data_avail_noticed_event)
    CloseHandle (win32_channel->data_avail_noticed_event);
  DeleteCriticalSection (&win32_channel->mutex);
884

885
  g_free (win32_channel->buffer);
886
  g_slist_free (win32_channel->watches);
887 888 889
  g_free (win32_channel);
}

890 891 892
static GSource *
g_io_win32_msg_create_watch (GIOChannel    *channel,
			     GIOCondition   condition)
893
{
894 895 896
  GIOWin32Watch *watch;
  GSource *source;

897
  source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
898
  watch = (GIOWin32Watch *)source;
899 900 901
  
  watch->channel = channel;
  g_io_channel_ref (channel);
902
  
903
  watch->condition = condition;
904
  
905 906
  watch->pollfd.fd = G_WIN32_MSG_HANDLE;
  watch->pollfd.events = condition;
907
  
908
  g_source_add_poll (source, &watch->pollfd);
909
  
910
  return source;
911 912
}

913
static GIOStatus
914
g_io_win32_fd_read (GIOChannel *channel,
915
		    gchar      *buf,
916 917 918
		    gsize       count,
		    gsize      *bytes_read,
		    GError    **err)
919
{
920
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
921
  gint result;
922
  
923 924 925 926
  if (win32_channel->debug)
    g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
	     win32_channel->fd, count);
  
927 928
  if (win32_channel->thread_id)
    {
929
      return buffer_read (win32_channel, buf, count, bytes_read, err);
930
    }
931 932

  result = read (win32_channel->fd, buf, count);
933

934 935 936
  if (win32_channel->debug)
    g_print ("g_io_win32_fd_read: read() = %d\n", result);

937 938 939
  if (result < 0)
    {
      *bytes_read = 0;
940

941
      switch (errno)
942 943
        {
#ifdef EAGAIN
944 945
	case EAGAIN:
	  return G_IO_STATUS_AGAIN;
946
#endif
947 948 949 950 951
	default:
	  g_set_error (err, G_IO_CHANNEL_ERROR,
		       g_io_channel_error_from_errno (errno),
		       g_strerror (errno));
	  return G_IO_STATUS_ERROR;
952
        }
953
    }
954 955 956 957

  *bytes_read = result;

  return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
958
}
959

960 961 962 963 964 965
static GIOStatus
g_io_win32_fd_write (GIOChannel  *channel,
		     const gchar *buf,
		     gsize        count,
		     gsize       *bytes_written,
		     GError     **err)
966
{
967
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
968
  gint result;
969
  
970
  result = write (win32_channel->fd, buf, count);
971 972 973
  if (win32_channel->debug)
    g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
	     win32_channel->fd, count, result);
974

975 976 977
  if (result < 0)
    {
      *bytes_written = 0;
978

979
      switch (errno)
980 981
        {
#ifdef EAGAIN
982 983
	case EAGAIN:
	  return G_IO_STATUS_AGAIN;
984
#endif
985 986 987 988 989
	default:
	  g_set_error (err, G_IO_CHANNEL_ERROR,
		       g_io_channel_error_from_errno (errno),
		       g_strerror (errno));
	  return G_IO_STATUS_ERROR;
990
        }
Tor Lillqvist's avatar