iochannel.c

来自「GNet是一个简单的网络库。它是目标定向的」· C语言 代码 · 共 837 行 · 第 1/2 页

C
837
字号
  g_return_if_fail (id != NULL);  state = (GNetIOChannelWriteAsyncState*) id;  if (delete_buffer)    g_free(state->buffer);  /* Don't delete state if we're in an upcall.  We'll do it after the     upcall. */  if (state->in_upcall)    return;  while (g_source_remove_by_user_data(state))    ;  g_free(state);}/* called internally only */static voidwrite_async_cancel (GNetIOChannelWriteAsyncState* state){  while (g_source_remove_by_user_data(state))    ;  g_free(state);}static gboolean write_async_cb (GIOChannel* iochannel, GIOCondition condition, gpointer data){  GNetIOChannelWriteAsyncState* state;  state = (GNetIOChannelWriteAsyncState*) data;  g_return_val_if_fail (iochannel, FALSE);  g_return_val_if_fail (state, FALSE);  g_return_val_if_fail (iochannel == state->iochannel, FALSE);  /* Error */  if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))    {      state->in_upcall = TRUE;      (state->func)(iochannel, state->buffer, state->length, state->n,		    GNET_IOCHANNEL_WRITE_ASYNC_STATUS_ERROR, state->user_data);      state->in_upcall = FALSE;      write_async_cancel (state);      return FALSE;    }  /* Write */  else if (condition & G_IO_OUT)    {      guint bytes_written;      if (g_io_channel_write(iochannel, 			     &state->buffer[state->n], 			     state->length - state->n,			     &bytes_written) != G_IO_ERROR_NONE)	{	  state->in_upcall = TRUE;	  state->func(iochannel, state->buffer, state->length, state->n,		      GNET_IOCHANNEL_WRITE_ASYNC_STATUS_ERROR, state->user_data);	  state->in_upcall = FALSE;	  write_async_cancel (state);	  return FALSE;	}      state->n += bytes_written;      if (state->n == state->length)	{	  state->in_upcall = TRUE; /* delay user cancelation */	  state->func(iochannel, state->buffer, state->length, state->n,		      GNET_IOCHANNEL_WRITE_ASYNC_STATUS_OK, state->user_data);	  state->in_upcall = FALSE;	  write_async_cancel (state);	  return FALSE;	}      return TRUE;    }  return FALSE;}static gboolean write_async_timeout_cb (gpointer data){  GNetIOChannelWriteAsyncState* state;  state = (GNetIOChannelWriteAsyncState*) data;  g_return_val_if_fail (state != NULL, FALSE);  state->in_upcall = TRUE;  state->func(state->iochannel, state->buffer, state->length, state->n,	      GNET_IOCHANNEL_WRITE_ASYNC_STATUS_TIMEOUT, state->user_data);  state->in_upcall = FALSE;  write_async_cancel(state);  return FALSE;}/* ************************************************************ */typedef struct _GNetIOChannelReadAsyncState{  GIOChannel* iochannel;  gboolean read_one;  gboolean my_buffer;  gchar* buffer;  guint max_len;  guint length;  guint offset;  guint timeout;  guint watch;  guint timer;  GNetIOChannelReadAsyncCheckFunc check_func;  gpointer check_user_data;  GNetIOChannelReadAsyncFunc func;  gpointer user_data;  gboolean in_upcall;} GNetIOChannelReadAsyncState;static gboolean read_async_cb (GIOChannel* iochannel, GIOCondition condition, gpointer data);static gboolean read_async_timeout_cb (gpointer data);GNetIOChannelReadAsyncIDgnet_io_channel_read_async (GIOChannel* iochannel, 			   gchar* buffer, guint length, guint timeout, 			   gboolean read_one_byte_at_a_time, 			   GNetIOChannelReadAsyncCheckFunc check_func, 			   gpointer check_user_data,			   GNetIOChannelReadAsyncFunc func, 	    			   gpointer user_data){  GNetIOChannelReadAsyncState* state;  g_return_val_if_fail (iochannel, NULL);  g_return_val_if_fail (check_func, NULL);  g_return_val_if_fail (func, NULL);  g_return_val_if_fail (buffer || (!buffer && length), NULL);  state = g_new0 (GNetIOChannelReadAsyncState, 1);  state->iochannel = iochannel;  state->read_one = read_one_byte_at_a_time;  if (buffer)    {      state->my_buffer = FALSE;      state->buffer = buffer;      state->max_len = length;      state->length = length;      state->offset = 0;    }  else    {      state->my_buffer = TRUE;      state->buffer = NULL;      state->max_len = length;      state->length = 0;      state->offset = 0;    }  state->check_func = 		check_func;  state->check_user_data = 	check_user_data;  state->func = 		func;  state->user_data = 		user_data;  state->watch = g_io_add_watch (iochannel, 				 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, 				 read_async_cb, state);  state->timeout = timeout;  if (timeout > 0)    state->timer = g_timeout_add (timeout, read_async_timeout_cb, state);  return state;}/* called by user, possibly during upcalls */voidgnet_io_channel_read_async_cancel (GNetIOChannelReadAsyncID id){  GNetIOChannelReadAsyncState* state;  g_return_if_fail (id != NULL);  state = (GNetIOChannelReadAsyncState*) id;  if (state->in_upcall)    return;  g_source_remove (state->watch);  if (state->timer)    g_source_remove (state->timer);  if (state->my_buffer)    g_free(state->buffer);  g_free(state);}/* used internally */static voidread_async_cancel (GNetIOChannelReadAsyncState* state){  g_source_remove (state->watch);  if (state->timer)    g_source_remove (state->timer);  if (state->my_buffer)    g_free(state->buffer);  g_free(state);}static gboolean read_async_cb (GIOChannel* iochannel, GIOCondition condition, gpointer data){  GNetIOChannelReadAsyncState* state;  GIOError error;  guint bytes_to_read;  guint bytes_read;  gint bytes_processed;  state = (GNetIOChannelReadAsyncState*) data;  g_return_val_if_fail (iochannel, FALSE);  g_return_val_if_fail (state, FALSE);  g_return_val_if_fail (iochannel == state->iochannel, FALSE);  if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))    {      state->in_upcall = TRUE;      (state->func)(iochannel, GNET_IOCHANNEL_READ_ASYNC_STATUS_ERROR, 		    NULL, 0, state->user_data);      state->in_upcall = FALSE;      read_async_cancel(state);      return FALSE;    }  else if (condition & G_IO_IN)    {      /* Check if we should make the buffer larger */      if (state->my_buffer && state->length == state->offset)	{	  if (state->length)	    {	      state->length *= 2;	      state->buffer = g_realloc(state->buffer, state->length);	    }	  else	    {	      state->length = MIN (128, state->max_len);	      state->buffer = g_malloc(state->length);	    }	}      if (state->read_one)	bytes_to_read = 1;      else	bytes_to_read = state->length - state->offset;      /* Read in some stuff */      error = g_io_channel_read (iochannel, &state->buffer[state->offset], 				 bytes_to_read, &bytes_read);      state->offset += bytes_read;      if (error == G_IO_ERROR_AGAIN)	return TRUE;      else if (error != G_IO_ERROR_NONE)	{	  state->in_upcall = TRUE;	  state->func (iochannel, GNET_IOCHANNEL_READ_ASYNC_STATUS_ERROR, 		       NULL, 0, state->user_data);	  state->in_upcall = FALSE;	  read_async_cancel (state);	  return FALSE;	}      /* If we read nothing, that means EOF and we're done.  Note we do	 not send anything that might be in the buffer */      else if (bytes_read == 0)	{	  state->in_upcall = TRUE;	  state->func (iochannel, GNET_IOCHANNEL_READ_ASYNC_STATUS_OK, 		       NULL, 0, state->user_data);	  state->in_upcall = FALSE;	  read_async_cancel (state);	  return FALSE;	}      /* Check if we read something */    again:      bytes_processed = (state->check_func)(state->buffer, state->offset, state->check_user_data);      if (bytes_processed)	{	  state->in_upcall = TRUE;	  if (!state->func (iochannel, GNET_IOCHANNEL_READ_ASYNC_STATUS_OK, 			    state->buffer, bytes_processed, state->user_data))	    {	      state->in_upcall = FALSE;	      read_async_cancel (state);	      return FALSE;	    }	  state->in_upcall = FALSE;	  /* It is a programmer error if they called	     g_io_channel_read_async_cancel() in the upcall and	     returned TRUE (read more). */	  /* Move it over */	  g_memmove (state->buffer, &state->buffer[bytes_processed], 		     state->offset - bytes_processed);	  state->offset -= bytes_processed;	  goto again;	}      /* Check if we hit the max length.  If so, it's an error. */      if (state->offset >= state->max_len)	{	  state->in_upcall = TRUE;	  state->func(iochannel, GNET_IOCHANNEL_READ_ASYNC_STATUS_ERROR, 		      state->buffer, state->offset, state->user_data);	  state->in_upcall = FALSE;	  read_async_cancel (state);	  return FALSE;	}      /* Reset the timer */      if (state->timeout)	{	  if (state->timer)	    g_source_remove (state->timer);	  state->timer = g_timeout_add (state->timeout, 					read_async_timeout_cb, 					state);	}      return TRUE;    }  return FALSE;}static gboolean read_async_timeout_cb (gpointer data){  GNetIOChannelReadAsyncState* state;  state = (GNetIOChannelReadAsyncState*) data;  g_return_val_if_fail (state, FALSE);  state->in_upcall = TRUE;  (state->func)(state->iochannel, GNET_IOCHANNEL_READ_ASYNC_STATUS_TIMEOUT, 		NULL, 0, state->user_data);  state->in_upcall = FALSE;  read_async_cancel (state);  return FALSE;}gintgnet_io_channel_readany_check_func (gchar* buffer, guint length, 				   gpointer user_data){  return length;}gintgnet_io_channel_readline_check_func (gchar* buffer, guint length, 				     gpointer user_data){  guint i;  for (i = 0; i < length; ++i)    {      if (buffer[i] == '\n')	return i + 1;    }  return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?