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 + -
显示快捷键?