inetaddr.c

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

C
2,578
字号
    if (pipe(pipes) == -1)      return NULL;    /* Fork to do the look up. */  fork_again:    if ((pid = fork()) == 0)      {	int outfd = pipes[1];	gchar* name;	guchar len;		close (pipes[0]);	if (ia->name)	  name = g_strdup(ia->name);	else	  name = gnet_gethostbyaddr((char*) &((struct sockaddr_in*)&ia->sa)->sin_addr, 				    sizeof(struct in_addr), AF_INET);	/* Write the name to the pipe.  If we didn't get a name, we	   just write the canonical name. */	if (name)	  {	    guint lenint = strlen(name);	    if (lenint > 255)	      {		g_warning ("Truncating domain name: %s\n", name);		name[256] = '\0';		lenint = 255;	      }	    len = lenint;	    if ((write(outfd, &len, sizeof(len)) == -1) ||		(write(outfd, name, len) == -1) )	      g_warning ("Error writing to pipe: %s\n", g_strerror(errno));	  }	else	  {	    gchar buffer[INET_ADDRSTRLEN];	/* defined in netinet/in.h */	    guchar* p = (guchar*) &(GNET_SOCKADDR_IN(ia->sa).sin_addr);	    g_snprintf(buffer, sizeof(buffer), 		       "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);	    len = strlen(buffer);	    if ((write(outfd, &len, sizeof(len)) == -1) ||		(write(outfd, buffer, len) == -1))	      g_warning ("Error writing to pipe: %s\n", g_strerror(errno));	  }	/* Close the socket */	close (outfd);	/* Exit (we don't want atexit called, so do _exit instead) */	_exit(EXIT_SUCCESS);      }    /* Set up an IOChannel to read from the pipe */    else if (pid > 0)      {	close (pipes[1]);	/* Create a structure for the call back */	state = g_new0(GInetAddrReverseAsyncState, 1);	state->pid = pid;	state->fd = pipes[0];	state->iochannel = gnet_private_iochannel_new(pipes[0]);	state->watch = g_io_add_watch(state->iochannel,				      (G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL),				      gnet_inetaddr_get_name_async_cb, 				      state);      }    /* Try again */    else if (errno == EAGAIN)      {	sleep(0);	/* Yield the processor */	goto fork_again;      }    /* Else there was a goofy error */    else      {	g_warning ("fork error: %s (%d)\n", g_strerror(errno), errno);	return NULL;      }  }# endif  /* Set up state for callback */  g_assert (state);  state->ia = ia;  state->func = func;  state->data = data;# ifdef HAVE_LIBPTHREAD  {    pthread_mutex_unlock (&state->mutex);  }# endif  return state;}#ifdef HAVE_LIBPTHREAD	/* ********** UNIX Pthread ********** */static gboolean inetaddr_get_name_async_pthread_dispatch (gpointer data);/** *  gnet_inetaddr_get_name_async_cancel: *  @id: ID of the lookup * *  Cancel an asynchronous nice name lookup that was started with *  gnet_inetaddr_get_name_async(). *  */voidgnet_inetaddr_get_name_async_cancel(GInetAddrGetNameAsyncID id){  GInetAddrReverseAsyncState* state = (GInetAddrReverseAsyncState*) id;  pthread_mutex_lock (&state->mutex);  /* Check if the thread has finished and a reply is pending.  If a     reply is pending, cancel it and delete state. */  if (state->source)    {      g_free (state->name);      g_source_remove (state->source);      pthread_mutex_unlock (&state->mutex);      pthread_mutex_destroy (&state->mutex);      g_free (state);    }  /* Otherwise, the thread is still running.  Set the cancelled flag     and allow the thread to complete.  When the thread completes, it     will delete state.  We can't kill the thread because we'd loose     the resources allocated in gethostbyname_r. */  else    {      state->is_cancelled = TRUE;      pthread_mutex_unlock (&state->mutex);    }}static gbooleaninetaddr_get_name_async_pthread_dispatch (gpointer data){  GInetAddrReverseAsyncState* state = (GInetAddrReverseAsyncState*) data;  pthread_mutex_lock (&state->mutex);  if (state->ia->name)    g_free (state->ia->name);  state->ia->name = state->name;  /* Upcall */  (*state->func)(state->ia, GINETADDR_ASYNC_STATUS_OK, 		 state->ia->name, state->data);  /* Delete state */  g_source_remove (state->source);  pthread_mutex_unlock (&state->mutex);  pthread_mutex_destroy (&state->mutex);  memset (state, 0, sizeof(*state));  g_free (state);  return FALSE;}static void* inetaddr_get_name_async_pthread (void* arg){  void** args      = (void**) arg;  GInetAddr* ia    = (GInetAddr*) args[0];  GInetAddrReverseAsyncState* state = (GInetAddrReverseAsyncState*) args[1];  gchar* 	  name;  g_free (args);  /* Do lookup */  if (ia->name)    name = g_strdup (ia->name);  else    name = gnet_gethostbyaddr((char*) &((struct sockaddr_in*)&ia->sa)->sin_addr, 			      sizeof(struct in_addr), AF_INET);  /* Lock */  pthread_mutex_lock (&state->mutex);       /* If cancelled, destroy state and exit.  The main thread is no     longer using state. */  if (state->is_cancelled)    {      g_free (name);      gnet_inetaddr_delete (ia);      pthread_mutex_unlock (&state->mutex);      pthread_mutex_destroy (&state->mutex);      g_free (state);      return NULL;    }  /* Copy name to state */  if (name)    {      state->name = name;    }  else 	/* Lookup failed: name is canonical name */    {      gchar buffer[INET_ADDRSTRLEN];	/* defined in netinet/in.h */      guchar* p = (guchar*) &(GNET_SOCKADDR_IN(ia->sa).sin_addr);      g_snprintf (buffer, sizeof(buffer), 		 "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);      state->name = g_strdup(buffer);    }  gnet_inetaddr_delete (ia);  /* Add a source for reply */  state->source = g_idle_add_full (G_PRIORITY_DEFAULT, 				   inetaddr_get_name_async_pthread_dispatch,				   state, NULL);  /* Unlock */  pthread_mutex_unlock (&state->mutex);  /* Thread exits... */  return NULL;}#else		/* ********** UNIX process ********** */gboolean gnet_inetaddr_get_name_async_cb (GIOChannel* iochannel, 				 GIOCondition condition, 				 gpointer data){  GInetAddrReverseAsyncState* state = (GInetAddrReverseAsyncState*) data;  gchar* name = NULL;  g_return_val_if_fail (state, FALSE);  g_return_val_if_fail (!state->in_callback, FALSE);  /* Read from the pipe */  if (condition & G_IO_IN)    {      int rv;      char* buf;      int length;      buf = &state->buffer[state->len];      length = sizeof(state->buffer) - state->len;      if ((rv = read(state->fd, buf, length)) >= 0)	{	  state->len += rv;	  /* Return true if there's more to read */	  if ((state->len - 1) != state->buffer[0])	    return TRUE;	  /* Copy the name */	  name = g_new(gchar, state->buffer[0] + 1);	  memcpy (name, &state->buffer[1], state->buffer[0]);	  name[state->buffer[0]] = '\0';	  if (state->ia->name) 	    g_free(state->ia->name);	  state->ia->name = name;	  /* Remove the watch now in case we don't return immediately */	  g_source_remove (state->watch);	  /* Call back */	  state->in_callback = TRUE;	  (*state->func)(state->ia, GINETADDR_ASYNC_STATUS_OK, name, state->data);	  state->in_callback = FALSE;	  gnet_inetaddr_get_name_async_cancel(state);	  return FALSE;	}      /* otherwise, there was a read error */    }  /* otherwise, there was some error */  /* Call back */  state->in_callback = TRUE;  (*state->func)(state->ia, GINETADDR_ASYNC_STATUS_ERROR, NULL, state->data);  state->in_callback = FALSE;  gnet_inetaddr_get_name_async_cancel(state);  return FALSE;}voidgnet_inetaddr_get_name_async_cancel(GInetAddrGetNameAsyncID id){  GInetAddrReverseAsyncState* state = (GInetAddrReverseAsyncState*) id;  g_return_if_fail(state != NULL);  if (state->in_callback)    return;  g_source_remove (state->watch);  g_io_channel_unref (state->iochannel);  close (state->fd);  kill (state->pid, SIGKILL);  waitpid (state->pid, NULL, 0);  g_free(state);}#endif#else	/*********** Windows code ***********/GInetAddrGetNameAsyncIDgnet_inetaddr_get_name_async(GInetAddr* ia,			     GInetAddrGetNameAsyncFunc func,			     gpointer data){  GInetAddrReverseAsyncState* state;  struct sockaddr_in* sa_in;  g_return_val_if_fail(ia != NULL, NULL);  g_return_val_if_fail(func != NULL, NULL);  /* Create a structure for the call back */  state = g_new0(GInetAddrReverseAsyncState, 1);  state->ia = ia;  state->func = func;  state->data = data;  sa_in = (struct sockaddr_in*)&ia->sa;	  state->WSAhandle = (int) WSAAsyncGetHostByAddr(gnet_hWnd, GET_NAME_MSG,						 (const char*)&sa_in->sin_addr,						 (int) (sizeof(&sa_in->sin_addr)),						 (int)&sa_in->sin_family,						 state->hostentBuffer,						 sizeof(state->hostentBuffer));  if (!state->WSAhandle)    {      g_free(state);      return NULL;    }	  /*get a lock and insert the state into the hash */  WaitForSingleObject(gnet_Mutex, INFINITE);  g_hash_table_insert(gnet_hash, (gpointer)state->WSAhandle, (gpointer)state);  ReleaseMutex(gnet_Mutex);  return state;}gbooleangnet_inetaddr_get_name_async_cb (GIOChannel* iochannel,				 GIOCondition condition,				 gpointer data){  GInetAddrReverseAsyncState* state;  gchar* name;  struct hostent* result;  state = (GInetAddrReverseAsyncState*) data;  result = (struct hostent*)state->hostentBuffer;  if (state->errorcode)    {      (*state->func)(state->ia, GINETADDR_ASYNC_STATUS_ERROR, NULL, state->data);      return FALSE;    }  state->ia->name = g_strdup(result->h_name);  name = NULL;  name = g_strdup(state->ia->name);  (*state->func)(state->ia, GINETADDR_ASYNC_STATUS_OK, name, state->data);  g_free(state);  return FALSE;}voidgnet_inetaddr_get_name_async_cancel(GInetAddrGetNameAsyncID id){  GInetAddrReverseAsyncState* state = (GInetAddrReverseAsyncState*) id;  g_return_if_fail(state != NULL);  gnet_inetaddr_delete (state->ia);  WSACancelAsyncRequest((HANDLE)state->WSAhandle);  /*get a lock and remove the hash entry */  WaitForSingleObject(gnet_Mutex, INFINITE);  g_hash_table_remove(gnet_hash, (gpointer)state->WSAhandle);  ReleaseMutex(gnet_Mutex);  g_free(state);}#endif		/*********** End Windows code ***********//** *  gnet_inetaddr_get_canonical_name: *  @ia: Address to get the canonical name of. * *  Get the "canonical" name of an address (eg, for IP4 the dotted *  decimal name 141.213.8.59). * *  Returns: NULL if there was an error.  The caller is responsible *  for deleting the returned string. * **/gchar* gnet_inetaddr_get_canonical_name(const GInetAddr* ia){  gchar buffer[INET_ADDRSTRLEN];	/* defined in netinet/in.h */  guchar* p = (guchar*) &(GNET_SOCKADDR_IN(ia->sa).sin_addr);    g_return_val_if_fail (ia != NULL, NULL);  g_snprintf(buffer, sizeof(buffer), 	     "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);    return g_strdup(buffer);}/** *  gnet_inetaddr_get_port: *  @ia: Address to get the port number of. * *  Get the port number. *  Returns: the port number. */gintgnet_inetaddr_get_port(const GInetAddr* ia){  g_return_val_if_fail(ia != NULL, -1);  return (gint) g_ntohs(GNET_SOCKADDR_IN(ia->sa).sin_port);}/** *  gnet_inetaddr_set_port: *  @ia: Address to set the port number of. *  @port: New port number * *  Set the port number. * **/voidgnet_inetaddr_set_port(const GInetAddr* ia, guint port){  g_return_if_fail(ia != NULL);  GNET_SOCKADDR_IN(ia->sa).sin_port = g_htons(port);}/* **************************************** *//** *  gnet_inetaddr_is_canonical: *  @name: Name to check * *  Check if the domain name is canonical.  For IPv4, a canonical name *  is a dotted decimal name (eg, 141.213.8.59). * *  Returns: TRUE if @name is canonical; FALSE otherwise. * **/gbooleangnet_inetaddr_is_canonical (const gchar* name){  struct in_addr inaddr;  g_return_val_if_fail (name, FALSE);  return (inet_aton(name, &inaddr) != 0);}/** *  gnet_inetaddr_is_internet: *  @inetaddr: Address to check *  *  Check if the address is a sensible internet address.  This mean it *  is not private, reserved, loopback, multicast, or broadcast. * *  Note that private and loopback address are often valid addresses, *  so this should only be used to check for general Internet *  connectivity.  That is, if the address passes, it is reachable on *  the Internet. * *  Returns: TRUE if the address is an 'Internet' address; FALSE *  otherwise. * **/gbooleangnet_inetaddr_is_internet (const GInetAddr* inetaddr){  g_return_val_if_fail(inetaddr != NULL, FALSE);  if (!gnet_inetaddr_is_private(inetaddr) 	&&      !gnet_inetaddr_is_reserved(inetaddr) 	&&      !gnet_inetaddr_is_loopback(inetaddr) 	&&      !gnet_inetaddr_is_multicast(inetaddr) 	&&      !gnet_inetaddr_is_broadcast(inetaddr))    {      return TRUE;    }  return FALSE;}/** *  gnet_inetaddr_is_private: *  @inetaddr: Address to check * *  Check if the address is an address reserved for private networks *  or something else.  This includes: * *   10.0.0.0        -   10.255.255.255  (10/8 prefix) *   172.16.0.0      -   172.31.255.255  (172.16/12 prefix) *   192.168.0.0     -   192.168.255.255 (192.168/16 prefix) * *  (from RFC 1918.  See also draft-manning-dsua-02.txt) *  *  Returns: TRUE if the address is reserved for private networks; *  FALSE otherwise. * **/gbooleangnet_inetaddr_is_private (const GInetAddr* inetaddr){  guint addr;  g_return_val_if_fail (inetaddr != NULL, FALSE);  addr = GNET_SOCKADDR_IN(inetaddr->sa).sin_addr.s_addr;  addr = g_ntohl(addr);  if ((addr & 0xFF000000) == (10 << 24))    return TRUE;  if ((addr & 0xFFF00000) == 0xAC100000)    return TRUE;  if ((addr & 0xFFFF0000) == 0xC0A80000)    return TRUE;  return FALSE;}/** *  gnet_inetaddr_is_reserved: *  @inetaddr: Address to check * *  Check if the address is reserved for 'something'.  This excludes *  address reserved for private networks. * *  We check for: *    0.0.0.0/16  (top 16 bits are 0's) *    Class E (top 5 bits are 11110) * *  Returns: TRUE if the address is reserved for something; FALSE *  otherwise. * **/gbooleangnet_inetaddr_is_reserved (const GInetAddr* inetaddr){  guint addr;  g_return_val_if_fail (inetaddr != NULL, FALSE);  addr = GNET_SOCKADDR_IN(inetaddr->sa).sin_addr.s_addr;  addr = g_ntohl(addr);  if ((addr & 0xFFFF0000) == 0)    return TRUE;  if ((addr & 0xF8000000) == 0xF0000000)    return TRUE;  return FALSE;}/** *  gnet_inetaddr_is_loopback: *  @inetaddr: Address to check * *  Check if the address is a loopback address.  Loopback addresses *  have the prefix 127.0.0.1/16. *  *  Returns: TRUE if the address is a loopback address; FALSE *  otherwise. * **/gbooleangnet_inetaddr_is_loopback (const GInetAddr* inetaddr){  guint addr;  g_return_val_if_fail (inetaddr != NULL, FALSE);

⌨️ 快捷键说明

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