giowin32.c
来自「Linux下的多协议即时通讯程序源代码」· C语言 代码 · 共 858 行 · 第 1/2 页
C
858 行
LOCK (channel->mutex); if (channel->running && channel->wrp == channel->rdp) { if (channel->debug) g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n", channel->thread_id); channel->revents = 0; } UNLOCK (channel->mutex); } else if (channel->type == G_IO_WIN32_SOCKET) { LOCK (channel->mutex); channel->revents = 0; if (channel->debug) g_print ("g_io_win32_prepare: for thread %#x, setting data_avail_noticed\n", 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); UNLOCK (channel->mutex); } return ((watch->condition & buffer_condition) == watch->condition);}static gbooleang_io_win32_check (GSource *source){ MSG msg; GIOWin32Watch *watch = (GIOWin32Watch *)source; GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel; GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel); if (channel->debug) 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, watch->pollfd.events, watch->pollfd.revents, channel->revents); if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES) { watch->pollfd.revents = (watch->pollfd.events & channel->revents); } else { return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE)); } if (channel->type == G_IO_WIN32_SOCKET) { LOCK (channel->mutex); if (channel->debug) 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); UNLOCK (channel->mutex); } return ((watch->pollfd.revents | buffer_condition) & watch->condition);}static gbooleang_io_win32_dispatch (GSource *source, GSourceFunc callback, gpointer user_data){ GIOFunc func = (GIOFunc)callback; GIOWin32Watch *watch = (GIOWin32Watch *)source; GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel); if (!func) { g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n" "You must call g_source_connect()."); return FALSE; } return (*func) (watch->channel, (watch->pollfd.revents | buffer_condition) & watch->condition, user_data);}static voidg_io_win32_finalize (GSource *source){ GIOWin32Watch *watch = (GIOWin32Watch *)source; GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel; char send_buffer[] = "f"; LOCK (channel->mutex); if (channel->debug) g_print ("g_io_win32_finalize: channel with thread %#x\n", channel->thread_id); channel->watches = g_slist_remove (channel->watches, watch); SetEvent (channel->data_avail_noticed_event); if (channel->type == G_IO_WIN32_SOCKET) { /* Tell select_thread() to exit */ channel->needs_close = 1; /* Wake up select_thread() from its blocking select() */ send (channel->reset_send, send_buffer, sizeof (send_buffer), 0); } UNLOCK (channel->mutex); g_io_channel_unref (watch->channel);}GSourceFuncs g_io_watch_funcs = { g_io_win32_prepare, g_io_win32_check, g_io_win32_dispatch, g_io_win32_finalize, NULL, NULL};static GSource *g_io_win32_create_watch (GIOChannel *channel, GIOCondition condition, unsigned (__stdcall *thread) (void *parameter)){ GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel; GIOWin32Watch *watch; GSource *source; char send_buffer[] = "c"; source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch)); watch = (GIOWin32Watch *)source; 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) g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n", win32_channel->fd, condition, watch->pollfd.fd); LOCK (win32_channel->mutex); win32_channel->watches = g_slist_append (win32_channel->watches, watch); if (win32_channel->thread_id == 0) create_thread (win32_channel, condition, thread); else send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0); g_source_add_poll (source, &watch->pollfd); UNLOCK (win32_channel->mutex); return source;}static voidg_io_win32_free (GIOChannel *channel){ GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel; if (win32_channel->debug) g_print ("thread %#x: freeing channel, fd: %d\n", win32_channel->thread_id, win32_channel->fd); if (win32_channel->reset_send && win32_channel->reset_send != INVALID_SOCKET) closesocket (win32_channel->reset_send); if (win32_channel->reset_recv && win32_channel->reset_recv != INVALID_SOCKET) closesocket (win32_channel->reset_recv); 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); g_free (win32_channel->buffer); g_slist_free (win32_channel->watches); g_free (win32_channel);}static GIOStatusg_io_win32_sock_read (GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read, GError **err){ GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel; gint result; GIOChannelError error = G_IO_STATUS_NORMAL; GIOStatus internal_status = G_IO_STATUS_NORMAL; char send_buffer[] = "sr"; if (win32_channel->debug) g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n", win32_channel->fd, count);#ifdef WE_NEED_TO_HANDLE_WSAEINTRrepeat:#endif result = recv (win32_channel->fd, buf, count, 0); if (win32_channel->debug) g_print ("g_io_win32_sock_read: recv:%d\n", result); if (result == SOCKET_ERROR) { *bytes_read = 0; switch (WSAGetLastError ()) { case WSAEINVAL: error = G_IO_CHANNEL_ERROR_INVAL; break; case WSAEWOULDBLOCK: return G_IO_STATUS_AGAIN;#ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */ case WSAEINTR: goto repeat;#endif default: error = G_IO_CHANNEL_ERROR_FAILED; break; } g_set_error (err, G_IO_CHANNEL_ERROR, error, "Socket read error"); internal_status = G_IO_STATUS_ERROR; /* FIXME get all errors, better error messages */ } else { *bytes_read = result; if (result == 0) internal_status = G_IO_STATUS_EOF; } if ((internal_status == G_IO_STATUS_EOF) || (internal_status == G_IO_STATUS_ERROR)) { LOCK (win32_channel->mutex); SetEvent (win32_channel->data_avail_noticed_event); win32_channel->needs_close = 1; send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0); UNLOCK (win32_channel->mutex); } return internal_status;}static GIOStatusg_io_win32_sock_write (GIOChannel *channel, const gchar *buf, gsize count, gsize *bytes_written, GError **err){ GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel; gint result; GIOChannelError error = G_IO_STATUS_NORMAL; char send_buffer[] = "sw"; if (win32_channel->debug) g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n", win32_channel->fd, count);#ifdef WE_NEED_TO_HANDLE_WSAEINTRrepeat:#endif result = send (win32_channel->fd, buf, count, 0); if (win32_channel->debug) g_print ("g_io_win32_sock_write: send:%d\n", result); if (result == SOCKET_ERROR) { *bytes_written = 0; switch (WSAGetLastError ()) { case WSAEINVAL: error = G_IO_CHANNEL_ERROR_INVAL; break; case WSAEWOULDBLOCK: return G_IO_STATUS_AGAIN;#ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */ case WSAEINTR: goto repeat;#endif default: error = G_IO_CHANNEL_ERROR_FAILED; break; } g_set_error (err, G_IO_CHANNEL_ERROR, error, "Socket write error"); LOCK (win32_channel->mutex); SetEvent (win32_channel->data_avail_noticed_event); win32_channel->needs_close = 1; send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0); UNLOCK (win32_channel->mutex); return G_IO_STATUS_ERROR; /* FIXME get all errors, better error messages */ } else { *bytes_written = result; return G_IO_STATUS_NORMAL; }}static GIOStatusg_io_win32_sock_close (GIOChannel *channel, GError **err){ GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel; LOCK (win32_channel->mutex); if (win32_channel->running) { if (win32_channel->debug) g_print ("thread %#x: running, marking for later close\n", win32_channel->thread_id); win32_channel->running = FALSE; win32_channel->needs_close = TRUE; SetEvent(win32_channel->data_avail_noticed_event); } if (win32_channel->fd != -1) { if (win32_channel->debug) g_print ("thread %#x: closing socket %d\n", win32_channel->thread_id, win32_channel->fd); closesocket (win32_channel->fd); win32_channel->fd = -1; } UNLOCK (win32_channel->mutex); /* FIXME error detection? */ return G_IO_STATUS_NORMAL;}static GSource *g_io_win32_sock_create_watch (GIOChannel *channel, GIOCondition condition){ return g_io_win32_create_watch (channel, condition, select_thread);}static GIOStatusg_io_win32_set_flags (GIOChannel *channel, GIOFlags flags, GError **err){ GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel; if (win32_channel->debug) { g_print ("g_io_win32_set_flags: "); g_win32_print_gioflags (flags); g_print ("\n"); } g_warning ("g_io_win32_set_flags () not implemented.\n"); return G_IO_STATUS_NORMAL;}static GIOFlagsg_io_win32_sock_get_flags (GIOChannel *channel){ /* XXX Could do something here. */ return 0;}static GIOFuncs win32_channel_sock_funcs = { g_io_win32_sock_read, g_io_win32_sock_write, NULL, g_io_win32_sock_close, g_io_win32_sock_create_watch, g_io_win32_free, g_io_win32_set_flags, g_io_win32_sock_get_flags,};GIOChannel *wpurple_g_io_channel_win32_new_socket (int socket){ GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1); GIOChannel *channel = (GIOChannel *)win32_channel; g_io_channel_init (channel); g_io_channel_win32_init (win32_channel); init_reset_sockets (win32_channel); if (win32_channel->debug) g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket); channel->funcs = &win32_channel_sock_funcs; win32_channel->type = G_IO_WIN32_SOCKET; win32_channel->fd = socket; /* XXX: check this */ channel->is_readable = TRUE; channel->is_writeable = TRUE; channel->is_seekable = FALSE; return channel;}#if 0voidg_io_channel_win32_set_debug (GIOChannel *channel, gboolean flag){ GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel; win32_channel->debug = flag;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?