1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * giowin32.c: IO Channels for Win32.
5 * Copyright 1998 Owen Taylor and Tor Lillqvist
6 * Copyright 1999-2000 Tor Lillqvist and Craig Setera
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.
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.
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.
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/.
31 /* Define this to get (very) verbose logging of all channels */
32 /* #define G_IO_WIN32_DEBUG */
38 #include <winsock.h> /* Not everybody has winsock2 */
45 typedef struct _GIOWin32Channel GIOWin32Channel;
46 typedef struct _GIOWin32Watch GIOWin32Watch;
48 #define BUFFER_SIZE 4096
51 G_IO_WINDOWS_MESSAGES, /* Windows messages */
52 G_IO_FILE_DESC, /* Unix-like file descriptors from
53 * _open() or _pipe(). Read with read().
54 * Have to create separate thread to read.
56 G_IO_STREAM_SOCKET /* Stream sockets. Similar as fds, but
59 } GIOWin32ChannelType;
61 struct _GIOWin32Channel {
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.
67 GIOWin32ChannelType type;
71 /* This is used by G_IO_WINDOWS_MESSAGES channels */
72 HWND hwnd; /* handle of window, or NULL */
74 /* Following fields used by fd and socket channels for input */
76 /* Data is kept in a circular buffer. To be able to distinguish between
77 * empty and full buffer, we cannot fill it completely, but have to
78 * leave a one character gap.
80 * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
83 * Full: (wrp + 1) % BUFFER_SIZE == rdp
86 guchar *buffer; /* (Circular) buffer */
87 gint wrp, rdp; /* Buffer indices for writing and reading */
88 gboolean running; /* Is reader thread running. FALSE if
89 * EOF has been reached.
91 gboolean needs_close; /* If the channel has been closed while
92 * the reader thread was still running.
94 guint thread_id; /* If non-NULL has a reader thread, or has
97 HANDLE data_avail_event;
98 HANDLE space_avail_event;
99 CRITICAL_SECTION mutex;
101 /* Function that actually reads from fd */
102 int (*reader) (int fd, guchar *buf, int len);
105 #define LOCK(mutex) EnterCriticalSection (&mutex)
106 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
108 struct _GIOWin32Watch {
112 GIOCondition condition;
117 g_io_channel_win32_init (GIOWin32Channel *channel)
119 #ifdef G_IO_WIN32_DEBUG
120 channel->debug = TRUE;
122 if (getenv ("G_IO_WIN32_DEBUG") != NULL)
123 channel->debug = TRUE;
125 channel->debug = FALSE;
127 channel->buffer = NULL;
128 channel->running = FALSE;
129 channel->needs_close = FALSE;
130 channel->thread_id = 0;
131 channel->data_avail_event = NULL;
132 channel->space_avail_event = NULL;
133 InitializeCriticalSection (&channel->mutex);
137 create_events (GIOWin32Channel *channel)
139 SECURITY_ATTRIBUTES sec_attrs;
141 sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
142 sec_attrs.lpSecurityDescriptor = NULL;
143 sec_attrs.bInheritHandle = FALSE;
145 /* The data available event is manual reset, the space available event
146 * is automatic reset.
148 if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
149 || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
151 gchar *msg = g_win32_error_message (GetLastError ());
152 g_error ("Error creating event: %s", msg);
156 static unsigned __stdcall
157 reader_thread (void *parameter)
159 GIOWin32Channel *channel = parameter;
163 g_io_channel_ref ((GIOChannel *) channel);
166 g_print ("thread %#x: starting. pid:%#x, fd:%d, data_avail:%#x, space_avail:%#x\n",
168 (guint) GetCurrentProcessId (),
170 (guint) channel->data_avail_event,
171 (guint) channel->space_avail_event);
173 channel->buffer = g_malloc (BUFFER_SIZE);
174 channel->rdp = channel->wrp = 0;
175 channel->running = TRUE;
177 SetEvent (channel->space_avail_event);
179 while (channel->running)
181 LOCK (channel->mutex);
183 g_print ("thread %#x: rdp=%d, wrp=%d\n",
184 channel->thread_id, channel->rdp, channel->wrp);
185 if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
189 g_print ("thread %#x: resetting space_available\n",
191 ResetEvent (channel->space_avail_event);
193 g_print ("thread %#x: waiting for space\n", channel->thread_id);
194 UNLOCK (channel->mutex);
195 WaitForSingleObject (channel->space_avail_event, INFINITE);
196 LOCK (channel->mutex);
198 g_print ("thread %#x: rdp=%d, wrp=%d\n",
199 channel->thread_id, channel->rdp, channel->wrp);
202 buffer = channel->buffer + channel->wrp;
204 /* Always leave at least one byte unused gap to be able to
205 * distinguish between the full and empty condition...
207 nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
208 BUFFER_SIZE - channel->wrp);
211 g_print ("thread %#x: calling reader for %d bytes\n",
212 channel->thread_id, nbytes);
214 UNLOCK (channel->mutex);
216 nbytes = (*channel->reader) (channel->fd, buffer, nbytes);
218 LOCK (channel->mutex);
221 g_print ("thread %#x: got %d bytes, rdp=%d, wrp=%d\n",
222 channel->thread_id, nbytes, channel->rdp, channel->wrp);
227 channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
229 g_print ("thread %#x: rdp=%d, wrp=%d, setting data available\n",
230 channel->thread_id, channel->rdp, channel->wrp);
231 SetEvent (channel->data_avail_event);
232 UNLOCK (channel->mutex);
235 channel->running = FALSE;
237 g_print ("thread %#x: got EOF, rdp=%d, wrp=%d, setting data available\n",
238 channel->thread_id, channel->rdp, channel->wrp);
240 if (channel->needs_close)
243 g_print ("thread %#x: channel fd %d needs closing\n",
244 channel->thread_id, channel->fd);
245 if (channel->type == G_IO_FILE_DESC)
247 else if (channel->type == G_IO_STREAM_SOCKET)
248 closesocket (channel->fd);
252 SetEvent (channel->data_avail_event);
253 UNLOCK (channel->mutex);
255 g_io_channel_unref((GIOChannel *) channel);
257 /* No need to call _endthreadex(), the actual thread starter routine
258 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
259 * _endthreadex() for us.
262 CloseHandle (channel->thread_handle);
268 create_reader_thread (GIOWin32Channel *channel,
271 channel->reader = reader;
273 if ((channel->thread_handle =
274 (HANDLE) _beginthreadex (NULL, 0, reader_thread, channel, 0,
275 &channel->thread_id)) == 0)
276 g_warning ("Error creating reader thread: %s", strerror (errno));
277 WaitForSingleObject (channel->space_avail_event, INFINITE);
281 buffer_read (GIOWin32Channel *channel,
289 LOCK (channel->mutex);
291 g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
292 channel->thread_id, count, channel->rdp, channel->wrp);
294 if (channel->rdp == channel->wrp)
296 UNLOCK (channel->mutex);
298 g_print ("waiting for data from thread %#x\n", channel->thread_id);
299 WaitForSingleObject (channel->data_avail_event, INFINITE);
301 g_print ("done waiting for data from thread %#x\n", channel->thread_id);
302 LOCK (channel->mutex);
303 if (channel->rdp == channel->wrp && !channel->running)
305 UNLOCK (channel->mutex);
310 if (channel->rdp < channel->wrp)
311 nbytes = channel->wrp - channel->rdp;
313 nbytes = BUFFER_SIZE - channel->rdp;
314 UNLOCK (channel->mutex);
315 nbytes = MIN (left, nbytes);
317 g_print ("moving %d bytes from thread %#x\n",
318 nbytes, channel->thread_id);
319 memcpy (dest, channel->buffer + channel->rdp, nbytes);
322 LOCK (channel->mutex);
323 channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
325 g_print ("setting space available for thread %#x\n", channel->thread_id);
326 SetEvent (channel->space_avail_event);
328 g_print ("for thread %#x: rdp=%d, wrp=%d\n",
329 channel->thread_id, channel->rdp, channel->wrp);
330 if (channel->running && channel->rdp == channel->wrp)
333 g_print ("resetting data_available of thread %#x\n",
335 ResetEvent (channel->data_avail_event);
337 UNLOCK (channel->mutex);
339 /* We have no way to indicate any errors form the actual
340 * read() or recv() call in the reader thread. Should we have?
342 *error = G_IO_ERROR_NONE;
347 g_io_win32_prepare (GSource *source,
356 g_io_win32_check (GSource *source)
358 GIOWin32Watch *watch = (GIOWin32Watch *)source;
359 GIOWin32Channel *channel = (GIOWin32Channel *) watch->channel;
361 /* If the thread has died, we have encountered EOF. If the buffer
362 * also is emtpty set the HUP bit.
364 if (!channel->running && channel->rdp == channel->wrp)
367 g_print ("g_io_win32_check: setting G_IO_HUP thread %#x rdp=%d wrp=%d\n",
368 channel->thread_id, channel->rdp, channel->wrp);
369 watch->pollfd.revents |= G_IO_HUP;
373 return (watch->pollfd.revents & watch->condition);
377 g_io_win32_dispatch (GSource *source,
378 GSourceFunc callback,
381 GIOFunc func = (GIOFunc)callback;
382 GIOWin32Watch *watch = (GIOWin32Watch *)source;
386 g_warning ("GIOWin32Watch dispatched without callback\n"
387 "You must call g_source_connect().");
391 return (*func) (watch->channel,
392 watch->pollfd.revents & watch->condition,
397 g_io_win32_destroy (GSource *source)
399 GIOWin32Watch *watch = (GIOWin32Watch *)source;
401 g_io_channel_unref (watch->channel);
404 static GSourceFuncs win32_watch_funcs = {
412 g_io_win32_create_watch (GIOChannel *channel,
413 GIOCondition condition,
414 int (*reader) (int, guchar *, int))
416 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
417 GIOWin32Watch *watch;
420 source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
421 watch = (GIOWin32Watch *)source;
423 watch->channel = channel;
424 g_io_channel_ref (channel);
426 watch->condition = condition;
428 if (win32_channel->data_avail_event == NULL)
429 create_events (win32_channel);
431 watch->pollfd.fd = (gint) win32_channel->data_avail_event;
432 watch->pollfd.events = condition;
434 if (win32_channel->debug)
435 g_print ("g_io_win32_create_watch: fd:%d handle:%#x\n",
436 win32_channel->fd, watch->pollfd.fd);
438 if (win32_channel->thread_id == 0)
439 create_reader_thread (win32_channel, reader);
441 g_source_add_poll (source, &watch->pollfd);
447 g_io_win32_msg_read (GIOChannel *channel,
452 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
453 MSG msg; /* In case of alignment problems */
455 if (count < sizeof (MSG))
456 return G_IO_ERROR_INVAL;
458 if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
459 return G_IO_ERROR_AGAIN;
461 memmove (buf, &msg, sizeof (MSG));
462 *bytes_read = sizeof (MSG);
463 return G_IO_ERROR_NONE;
467 g_io_win32_msg_write (GIOChannel *channel,
470 guint *bytes_written)
472 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
475 if (count != sizeof (MSG))
476 return G_IO_ERROR_INVAL;
478 /* In case of alignment problems */
479 memmove (&msg, buf, sizeof (MSG));
480 if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
481 return G_IO_ERROR_UNKNOWN;
483 *bytes_written = sizeof (MSG);
484 return G_IO_ERROR_NONE;
488 g_io_win32_no_seek (GIOChannel *channel,
492 return G_IO_ERROR_UNKNOWN;
496 g_io_win32_msg_close (GIOChannel *channel)
498 /* Nothing to be done. Or should we set hwnd to some invalid value? */
502 g_io_win32_free (GIOChannel *channel)
504 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
506 if (win32_channel->debug)
507 g_print ("thread %#x: freeing channel, fd: %d\n",
508 win32_channel->thread_id,
511 if (win32_channel->buffer)
513 CloseHandle (win32_channel->data_avail_event);
514 CloseHandle (win32_channel->space_avail_event);
515 DeleteCriticalSection (&win32_channel->mutex);
518 g_free (win32_channel->buffer);
519 g_free (win32_channel);
523 g_io_win32_msg_create_watch (GIOChannel *channel,
524 GIOCondition condition)
526 GIOWin32Watch *watch;
529 source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
530 watch = (GIOWin32Watch *)source;
532 watch->channel = channel;
533 g_io_channel_ref (channel);
535 watch->condition = condition;
537 watch->pollfd.fd = G_WIN32_MSG_HANDLE;
538 watch->pollfd.events = condition;
540 g_source_add_poll (source, &watch->pollfd);
546 g_io_win32_fd_read (GIOChannel *channel,
551 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
555 if (win32_channel->debug)
556 g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
557 win32_channel->fd, count);
559 if (win32_channel->thread_id)
561 result = buffer_read (win32_channel, buf, count, &error);
569 *bytes_read = result;
570 return G_IO_ERROR_NONE;
574 result = read (win32_channel->fd, buf, count);
580 return G_IO_ERROR_INVAL;
582 return G_IO_ERROR_UNKNOWN;
586 *bytes_read = result;
587 return G_IO_ERROR_NONE;
592 g_io_win32_fd_write (GIOChannel *channel,
595 guint *bytes_written)
597 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
600 result = write (win32_channel->fd, buf, count);
601 if (win32_channel->debug)
602 g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
603 win32_channel->fd, count, result);
611 return G_IO_ERROR_INVAL;
613 return G_IO_ERROR_AGAIN;
615 return G_IO_ERROR_UNKNOWN;
620 *bytes_written = result;
621 return G_IO_ERROR_NONE;
626 g_io_win32_fd_seek (GIOChannel *channel,
630 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
646 g_warning ("g_io_win32_fd_seek: unknown seek type");
647 return G_IO_ERROR_UNKNOWN;
650 result = lseek (win32_channel->fd, offset, whence);
657 return G_IO_ERROR_INVAL;
659 return G_IO_ERROR_UNKNOWN;
663 return G_IO_ERROR_NONE;
667 g_io_win32_fd_close (GIOChannel *channel)
669 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
671 if (win32_channel->debug)
672 g_print ("thread %#x: closing fd %d\n",
673 win32_channel->thread_id,
675 LOCK (win32_channel->mutex);
676 if (win32_channel->running)
678 if (win32_channel->debug)
679 g_print ("thread %#x: running, marking fd %d for later close\n",
680 win32_channel->thread_id, win32_channel->fd);
681 win32_channel->running = FALSE;
682 win32_channel->needs_close = TRUE;
683 SetEvent (win32_channel->data_avail_event);
687 if (win32_channel->debug)
688 g_print ("closing fd %d\n", win32_channel->fd);
689 close (win32_channel->fd);
690 if (win32_channel->debug)
691 g_print ("closed fd %d, setting to -1\n",
693 win32_channel->fd = -1;
695 UNLOCK (win32_channel->mutex);
703 return read (fd, buf, len);
707 g_io_win32_fd_create_watch (GIOChannel *channel,
708 GIOCondition condition)
710 return g_io_win32_create_watch (channel, condition, fd_reader);
714 g_io_win32_sock_read (GIOChannel *channel,
719 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
723 if (win32_channel->thread_id)
725 result = buffer_read (win32_channel, buf, count, &error);
733 *bytes_read = result;
734 return G_IO_ERROR_NONE;
738 result = recv (win32_channel->fd, buf, count, 0);
743 return G_IO_ERROR_UNKNOWN;
747 *bytes_read = result;
748 return G_IO_ERROR_NONE;
753 g_io_win32_sock_write (GIOChannel *channel,
756 guint *bytes_written)
758 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
761 result = send (win32_channel->fd, buf, count, 0);
763 if (result == SOCKET_ERROR)
766 switch (WSAGetLastError ())
769 return G_IO_ERROR_INVAL;
772 return G_IO_ERROR_AGAIN;
774 return G_IO_ERROR_UNKNOWN;
779 *bytes_written = result;
780 return G_IO_ERROR_NONE;
785 g_io_win32_sock_close (GIOChannel *channel)
787 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
789 if (win32_channel->debug)
790 g_print ("thread %#x: closing socket %d\n",
791 win32_channel->thread_id,
793 closesocket (win32_channel->fd);
794 win32_channel->fd = -1;
802 return recv (fd, buf, len, 0);
806 g_io_win32_sock_create_watch (GIOChannel *channel,
807 GIOCondition condition)
809 return g_io_win32_create_watch (channel, condition, sock_reader);
812 static GIOFuncs win32_channel_msg_funcs = {
814 g_io_win32_msg_write,
816 g_io_win32_msg_close,
817 g_io_win32_msg_create_watch,
821 static GIOFuncs win32_channel_fd_funcs = {
826 g_io_win32_fd_create_watch,
830 static GIOFuncs win32_channel_sock_funcs = {
831 g_io_win32_sock_read,
832 g_io_win32_sock_write,
834 g_io_win32_sock_close,
835 g_io_win32_sock_create_watch,
840 g_io_channel_win32_new_messages (guint hwnd)
842 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
843 GIOChannel *channel = (GIOChannel *) win32_channel;
845 g_io_channel_init (channel);
846 g_io_channel_win32_init (win32_channel);
847 if (win32_channel->debug)
848 g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
849 channel->funcs = &win32_channel_msg_funcs;
850 win32_channel->type = G_IO_WINDOWS_MESSAGES;
851 win32_channel->hwnd = (HWND) hwnd;
857 g_io_channel_win32_new_fd (gint fd)
859 GIOWin32Channel *win32_channel;
863 if (fstat (fd, &st) == -1)
865 g_warning ("%d isn't a (emulated) file descriptor", fd);
869 win32_channel = g_new (GIOWin32Channel, 1);
870 channel = (GIOChannel *) win32_channel;
872 g_io_channel_init (channel);
873 g_io_channel_win32_init (win32_channel);
874 if (win32_channel->debug)
875 g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
876 channel->funcs = &win32_channel_fd_funcs;
877 win32_channel->type = G_IO_FILE_DESC;
878 win32_channel->fd = fd;
884 g_io_channel_win32_get_fd (GIOChannel *channel)
886 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
888 return win32_channel->fd;
892 g_io_channel_win32_new_stream_socket (int socket)
894 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
895 GIOChannel *channel = (GIOChannel *) win32_channel;
897 g_io_channel_init (channel);
898 g_io_channel_win32_init (win32_channel);
899 if (win32_channel->debug)
900 g_print ("g_io_channel_win32_new_stream_socket: socket = %d\n", socket);
901 channel->funcs = &win32_channel_sock_funcs;
902 win32_channel->type = G_IO_STREAM_SOCKET;
903 win32_channel->fd = socket;
909 g_io_channel_unix_new (gint fd)
913 if (fstat (fd, &st) == 0)
914 return g_io_channel_win32_new_fd (fd);
916 if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
917 return g_io_channel_win32_new_stream_socket(fd);
919 g_warning ("%d isn't a file descriptor or a socket", fd);
924 g_io_channel_unix_get_fd (GIOChannel *channel)
926 return g_io_channel_win32_get_fd (channel);
930 g_io_channel_win32_set_debug (GIOChannel *channel,
933 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
935 win32_channel->debug = flag;
939 g_io_channel_win32_poll (GPollFD *fds,
945 g_return_val_if_fail (n_fds >= 0, 0);
947 result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
953 g_io_channel_win32_make_pollfd (GIOChannel *channel,
954 GIOCondition condition,
957 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
959 if (win32_channel->data_avail_event == NULL)
960 create_events (win32_channel);
962 fd->fd = (gint) win32_channel->data_avail_event;
963 fd->events = condition;
965 if (win32_channel->thread_id == 0)
966 if (win32_channel->type == G_IO_FILE_DESC)
967 create_reader_thread (win32_channel, fd_reader);
968 else if (win32_channel->type == G_IO_STREAM_SOCKET)
969 create_reader_thread (win32_channel, sock_reader);