⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ares_process.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright 1998 by the Massachusetts Institute of Technology. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * M.I.T. makes no representations about the suitability of * this software for any purpose.  It is provided "as is" * without express or implied warranty. * * CHANGELOG: this file has been modified by Sergio Perez Alca駃z <serpeal@upvnet.upv.es>  *            Departamento de Inform醫ica de Sistemas y Computadores           *            Universidad Polit閏nica de Valencia                              *            Valencia (Spain)     *            Date: April 2003                                           * */#include "ares_private.h"#include "ares_dns.h"static void write_tcp_data(ares_channel channel, fd_set *write_fds,			   time_t now);static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now);static void read_udp_packets(ares_channel channel, fd_set *read_fds,			     time_t now);static void process_timeouts(ares_channel channel, time_t now);static void process_answer(ares_channel channel, unsigned char *abuf,			   int alen, int whichserver, int tcp, int now);static void handle_error(ares_channel channel, int whichserver, time_t now);static void next_server(ares_channel channel, struct query *query, time_t now);static int open_tcp_socket(ares_channel channel, struct server_state *server);static int open_udp_socket(ares_channel channel, struct server_state *server);static int same_questions(const unsigned char *qbuf, int qlen,			  const unsigned char *abuf, int alen);static void end_query(ares_channel channel, struct query *query, int status,		      unsigned char *abuf, int alen);/* Something interesting happened on the wire, or there was a timeout. * See what's up and respond accordingly. */void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds){  time_t now;  time(&now);  write_tcp_data(channel, write_fds, now);  read_tcp_data(channel, read_fds, now);  read_udp_packets(channel, read_fds, now);  process_timeouts(channel, now);}/* If any TCP sockets select true for writing, write out queued data * we have for them. */static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now){  struct server_state *server;  struct send_request *sendreq;#ifdef HAVE_WRITEV  struct iovec *vec;#endif  int i, n, count;  for (i = 0; i < channel->nservers; i++)    {      /* Make sure server has data to send and is selected in write_fds. */      server = &channel->servers[i];      if (!server->qhead || server->tcp_socket == -1	  || !FD_ISSET(server->tcp_socket, write_fds))	continue;      /* Count the number of send queue items. */      n = 0;      for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)	n++;#ifdef HAVE_WRITEV      /* Allocate iovecs so we can send all our data at once. */      vec = malloc(n * sizeof(struct iovec));      if (vec)	{	  /* Fill in the iovecs and send. */	  n = 0;	  for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)	    {	      vec[n].iov_base = (char *) sendreq->data;	      vec[n].iov_len = sendreq->len;	      n++;	    }	  count = writev(server->tcp_socket, vec, n);	  free(vec);	  if (count < 0)	    {	      handle_error(channel, i, now);	      continue;	    }	  /* Advance the send queue by as many bytes as we sent. */	  while (count)	    {	      sendreq = server->qhead;	      if (count >= sendreq->len)		{		  count -= sendreq->len;		  server->qhead = sendreq->next;		  if (server->qhead == NULL)		    server->qtail = NULL;		  free(sendreq);		}	      else		{		  sendreq->data += count;		  sendreq->len -= count;		  break;		}	    }	}      else#endif /* HAVE_WRITEV */	{	  /* Can't allocate iovecs; just send the first request. */	  sendreq = server->qhead;	  count = write(server->tcp_socket, (void *) sendreq->data, sendreq->len);	  if (count < 0)	    {	      handle_error(channel, i, now);	      continue;	    }	  /* Advance the send queue by as many bytes as we sent. */	  if (count == sendreq->len)	    {	      server->qhead = sendreq->next;	      if (server->qhead == NULL)		server->qtail = NULL;	      free(sendreq);	    }	  else	    {	      sendreq->data += count;	      sendreq->len -= count;	    }	}    }}/* If any TCP socket selects true for reading, read some data, * allocate a buffer if we finish reading the length word, and process * a packet if we finish reading one. */static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now){  struct server_state *server;  int i, count;  for (i = 0; i < channel->nservers; i++)    {      /* Make sure the server has a socket and is selected in read_fds. */      server = &channel->servers[i];      if (server->tcp_socket == -1 || !FD_ISSET(server->tcp_socket, read_fds))	continue;      if (server->tcp_lenbuf_pos != 2)	{	  /* We haven't yet read a length word, so read that (or	   * what's left to read of it).	   */	  count = read(server->tcp_socket,		       server->tcp_lenbuf + server->tcp_lenbuf_pos,		       2 - server->tcp_lenbuf_pos);	  if (count <= 0)	    {	      handle_error(channel, i, now);	      continue;	    }	  server->tcp_lenbuf_pos += count;	  if (server->tcp_lenbuf_pos == 2)	    {	      /* We finished reading the length word.  Decode the               * length and allocate a buffer for the data.	       */	      server->tcp_length = server->tcp_lenbuf[0] << 8		| server->tcp_lenbuf[1];	      server->tcp_buffer = malloc(server->tcp_length);	      if (!server->tcp_buffer)		handle_error(channel, i, now);	      server->tcp_buffer_pos = 0;	    }	}      else	{	  /* Read data into the allocated buffer. */	  count = read(server->tcp_socket,		       server->tcp_buffer + server->tcp_buffer_pos,		       server->tcp_length - server->tcp_buffer_pos);	  if (count <= 0)	    {	      handle_error(channel, i, now);	      continue;	    }	  server->tcp_buffer_pos += count;	  if (server->tcp_buffer_pos == server->tcp_length)	    {	      /* We finished reading this answer; process it and               * prepare to read another length word.	       */	      process_answer(channel, server->tcp_buffer, server->tcp_length,			     i, 1, now);	      free(server->tcp_buffer);	      server->tcp_buffer = NULL;	      server->tcp_lenbuf_pos = 0;	    }	}    }}/* If any UDP sockets select true for reading, process them. */static void read_udp_packets(ares_channel channel, fd_set *read_fds,			     time_t now){  struct server_state *server;  int i, count;  unsigned char buf[PACKETSZ + 1];  for (i = 0; i < channel->nservers; i++)    {      /* Make sure the server has a socket and is selected in read_fds. */      server = &channel->servers[i];      if (server->udp_socket == -1 || !FD_ISSET(server->udp_socket, read_fds))	continue;      count = recv(server->udp_socket, buf, sizeof(buf), 0);      if (count <= 0)	handle_error(channel, i, now);      process_answer(channel, buf, count, i, 0, now);    }}/* If any queries have timed out, note the timeout and move them on. */static void process_timeouts(ares_channel channel, time_t now){  struct query *query, *next;  for (query = channel->queries; query; query = next)    {      next = query->next;      if (query->timeout != 0 && now >= query->timeout)	{	  query->error_status = ARES_ETIMEOUT;	  next_server(channel, query, now);	}    }}/* Handle an answer from a server. */static void process_answer(ares_channel channel, unsigned char *abuf,			   int alen, int whichserver, int tcp, int now){  int id, tc, rcode;  struct query *query;  /* If there's no room in the answer for a header, we can't do much   * with it. */  if (alen < HFIXEDSZ)    return;  /* Grab the query ID, truncate bit, and response code from the packet. */  id = DNS_HEADER_QID(abuf);  tc = DNS_HEADER_TC(abuf);  rcode = DNS_HEADER_RCODE(abuf);  /* Find the query corresponding to this packet. */  for (query = channel->queries; query; query = query->next)    {      if (query->qid == id)	break;    }  if (!query)    return;  /* If we got a truncated UDP packet and are not ignoring truncation,   * don't accept the packet, and switch the query to TCP if we hadn't   * done so already.   */  if ((tc || alen > PACKETSZ) && !tcp && !(channel->flags & ARES_FLAG_IGNTC))    {      if (!query->using_tcp)	{	  query->using_tcp = 1;	  ares__send_query(channel, query, now);	}      return;    }  /* Limit alen to PACKETSZ if we aren't using TCP (only relevant if we   * are ignoring truncation.   */  if (alen > PACKETSZ && !tcp)    alen = PACKETSZ;  /* If we aren't passing through all error packets, discard packets

⌨️ 快捷键说明

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