Example #1
0
/* If any queries have timed out, note the timeout and move them on. */
static void process_timeouts(ares_channel channel, struct timeval *now)
{
  time_t t;  /* the time of the timeouts we're processing */
  struct query *query;
  struct list_node* list_head;
  struct list_node* list_node;

  /* Process all the timeouts that have fired since the last time we processed
   * timeouts. If things are going well, then we'll have hundreds/thousands of
   * queries that fall into future buckets, and only a handful of requests
   * that fall into the "now" bucket, so this should be quite quick.
   */
  for (t = channel->last_timeout_processed; t <= now->tv_sec; t++)
    {
      list_head = &(channel->queries_by_timeout[t % ARES_TIMEOUT_TABLE_SIZE]);
      for (list_node = list_head->next; list_node != list_head; )
        {
          query = list_node->data;
          list_node = list_node->next;  /* in case the query gets deleted */
          if (query->timeout.tv_sec && ares__timedout(now, &query->timeout))
            {
              query->error_status = ARES_ETIMEOUT;
              ++query->timeouts;
              next_server(channel, query, now);
            }
        }
     }
  channel->last_timeout_processed = now->tv_sec;
}
Example #2
0
static void handle_error(ares_channel channel, int whichserver, time_t now)
{
  struct query *query;

  /* Reset communications with this server. */
  //fprintf(stderr,"kennard:ares:handle_error: ...\n");
  ares__close_poll(channel, whichserver);
  ares__close_sockets(&channel->servers[whichserver]);

  /* Tell all queries talking to this server to move on and not try
   * this server again.
   */
  for (query = channel->queries; query != 0; query = query->next)
    {
		assert( query != 0 );
		assert( channel->queries != 0 );

      if (query->server == whichserver)
	{
	  query->skip_server[whichserver] = 1;
#if 0 // !cj! - this seem to corrput memory when it is called 
	  next_server(channel, query, now);
#endif
	}
    }
}
Example #3
0
static gboolean send_timeout(gpointer user_data)
{
	DBG("send timeout (retries %d)", retries);

	if (retries++ == NTP_SEND_RETRIES)
		next_server();
	else
		send_packet(transmit_fd, timeserver);

	return FALSE;
}
/* send to result to client */
void send_result_to_client(int sockfd, char *function, char **own_service_table, int *param_list, int param_len, char **client_server_list, int client_server_list_len, char *own_server_name, struct ServiceList *service_list, char *func_name){
	int i=0;
	char *saveptr1;
	char *str;
	char *ns;
	int seed;
	int n;
	srand(time(NULL));
	n = rand() % 100;
	for(i=0; i<own_service_table_size; i++){
		char s[strlen(own_service_table[i])+1];
		strcpy(s, own_service_table[i]);
		str = strtok_r(s, " ", &saveptr1);
		if( strcmp(func_name, str)==0 ){
			if( strcmp(own_service_table[i], function)==0 ){
				break;
			}
			else{
				send_mismatch_message(sockfd, own_service_table[i]);
				return;
			}
		}
	}
	
	int service_num = i;
	ns = next_server(function, service_list, client_server_list, client_server_list_len);
	if( strcmp(own_service_table[i], "get_int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = get_int(param_list[0]);
			send_result_message(sockfd, function, r);
		}			
	}
	else if( strcmp(own_service_table[i], "add int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = add(param_list[0], param_list[1]);
			send_result_message(sockfd, function, r);
		}			
	}
	else if( strcmp(own_service_table[i], "sub int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = sub(param_list[0], param_list[1]);
			send_result_message(sockfd, function, r);
		}			
	}
	else if( strcmp(own_service_table[i], "mul int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = mul(param_list[0], param_list[1]);
			send_result_message(sockfd, function, r);
		}			
	}
	else if( strcmp(own_service_table[i], "a int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = a(param_list[0], param_list[1]);
			send_result_message(sockfd, function, r);
		}			
	}
	else if( strcmp(own_service_table[i], "b int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = b(param_list[0], param_list[1]);
			send_result_message(sockfd, function, r);
		}			
	}
	else if( strcmp(own_service_table[i], "c int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = c(param_list[0], param_list[1]);
			send_result_message(sockfd, function, r);
		}			
	}
	else if( strcmp(own_service_table[i], "d int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = d(param_list[0], param_list[1]);
			send_result_message(sockfd, function, r);
		}			
	}
	else if( strcmp(own_service_table[i], "e int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = e(param_list[0], param_list[1]);
			send_result_message(sockfd, function, r);
		}			
	}
	else if( strcmp(own_service_table[i], "f int int")==0 ){
		if (n < BUSY_PERCENT){
			if(ns == NULL){
				send_out_message(sockfd);
			}
			else{
				send_busy_message(sockfd, function, ns); 
			}
		}
		else{
			int r = f(param_list[0], param_list[1]);
			send_result_message(sockfd, function, r);
		}			
	}
	else{
		if(ns == NULL)
			send_out_message(sockfd);
		else{
			send_unknown_message(sockfd, function, ns);
		}
	}
	/* free */
	if(ns != NULL)
		free(ns);
}
Example #5
0
/* Hook up to a server
 */
static void connect_server(void)
{
  char pass[121], botserver[UHOSTLEN];
  int servidx;
  unsigned int botserverport = 0;

  lastpingcheck = 0;
  trying_server = now;
  empty_msgq();
  if (newserverport) {          /* Jump to specified server */
    curserv = -1;             /* Reset server list */
    strcpy(botserver, newserver);
    botserverport = newserverport;
    strcpy(pass, newserverpass);
    newserver[0] = 0;
    newserverport = 0;
    newserverpass[0] = 0;
  } else {
    if (curserv == -1)
      curserv = 999;
    pass[0] = 0;
  }
  if (!cycle_time) {
    struct chanset_t *chan;
    struct server_list *x = serverlist;

    if (!x && !botserverport) {
      putlog(LOG_SERV, "*", "No servers in server list");
      cycle_time = 300;
      return;
    }

    servidx = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
    if (servidx < 0) {
      putlog(LOG_SERV, "*",
             "NO MORE DCC CONNECTIONS -- Can't create server connection.");
      return;
    }

    if (connectserver[0])       /* drummer */
      do_tcl("connect-server", connectserver);
    check_tcl_event("connect-server");
    next_server(&curserv, botserver, &botserverport, pass);
#ifdef TLS
    putlog(LOG_SERV, "*", "%s [%s]:%s%d", IRC_SERVERTRY, botserver,
           use_ssl ? "+" : "", botserverport);
    dcc[servidx].ssl = use_ssl;
#else
    putlog(LOG_SERV, "*", "%s [%s]:%d", IRC_SERVERTRY, botserver,
           botserverport);
#endif
    dcc[servidx].port = botserverport;
    strcpy(dcc[servidx].nick, "(server)");
    strncpyz(dcc[servidx].host, botserver, UHOSTLEN);

    botuserhost[0] = 0;

    nick_juped = 0;
    for (chan = chanset; chan; chan = chan->next)
      chan->status &= ~CHAN_JUPED;

    dcc[servidx].timeval = now;
    dcc[servidx].sock = -1;
    dcc[servidx].u.dns->host = get_data_ptr(strlen(dcc[servidx].host) + 1);
    strcpy(dcc[servidx].u.dns->host, dcc[servidx].host);
    dcc[servidx].u.dns->cbuf = get_data_ptr(strlen(pass) + 1);
    strcpy(dcc[servidx].u.dns->cbuf, pass);
    dcc[servidx].u.dns->dns_success = server_resolve_success;
    dcc[servidx].u.dns->dns_failure = server_resolve_failure;
    dcc[servidx].u.dns->dns_type = RES_IPBYHOST;
    dcc[servidx].u.dns->type = &SERVER_SOCKET;

    if (server_cycle_wait)
      /* Back to 1st server & set wait time.
       * Note: Put it here, just in case the server quits on us quickly
       */
      cycle_time = server_cycle_wait;
    else
      cycle_time = 0;

    /* I'm resolving... don't start another server connect request */
    resolvserv = 1;
    /* Resolve the hostname. */
    dcc_dnsipbyhost(dcc[servidx].host);
  }
}
Example #6
0
void ares__send_query(ares_channel channel, struct query *query, time_t now)
{
  struct send_request *sendreq;
  struct server_state *server;

  server = &channel->servers[query->server];
  if (query->using_tcp)
    {
      int tryWrite = 0;
      /* Make sure the TCP socket for this server is set up and queue
       * a send request.
       */
      if (server->tcp_socket == -1)
	{
	  if (open_tcp_socket(channel, server) == -1)
	    {
	      query->skip_server[query->server] = 1;
	      next_server(channel, query, now);
	      return;
	    }
	  if ( channel->poll_cb_func ) {
	      // printf("ares_send_q: pollopen tcp fd=%d\n", server->tcp_socket);
	      (*(channel->poll_cb_func))( channel->poll_cb_data, channel,
		query->server, server->tcp_socket, ARES_POLLACTION_OPEN);
	  }
	}
      sendreq = malloc(sizeof(struct send_request));
      if (!sendreq)
	end_query(channel, query, ARES_ENOMEM, NULL, 0);
      sendreq->data = query->tcpbuf;
      sendreq->len = query->tcplen;
      sendreq->next = NULL;
      if (server->qtail) {
	  server->qtail->next = sendreq;
      } else {
	  server->qhead = sendreq;
          tryWrite = 1;
      }
      server->qtail = sendreq;
      query->timeout = 0;
      if ( tryWrite )
        {
#if 0
	  time_t now;
	  time(&now);
	  write_tcp_data(channel, query->server, now);
	  /* XXX: the write code doesn't seem to handle EAGAIN properly! */
#else
	  if ( channel->poll_cb_func )
              (*(channel->poll_cb_func))( channel->poll_cb_data,
	        channel, query->server,
		server->tcp_socket, ARES_POLLACTION_WRITEON);
#endif
        }
    }
  else
    {
      if (server->udp_socket == -1)
	{
	  if (open_udp_socket(channel, server) == -1)
	    {
	      //fprintf(stderr,"kennard:ares:send_query:open_udp failed\n");
	      query->skip_server[query->server] = 1;
	      next_server(channel, query, now);
	      return;
	    }
	  if ( channel->poll_cb_func ) {
	      // printf("ares_send_q: pollopen udp fd=%d\n", server->udp_socket);
	      (*(channel->poll_cb_func))( channel->poll_cb_data, channel,
	      	query->server, server->udp_socket, ARES_POLLACTION_OPEN);
	  }
	}
      if (send(server->udp_socket, query->qbuf, query->qlen, 0) == -1)
	{
	  //fprintf(stderr,"kennard:ares:send_query:send_udp failed\n");
	  query->skip_server[query->server] = 1;
	  next_server(channel, query, now);
	  return;
	}
      query->timeout = now
	  + ((query->itry == 0) ? channel->timeout
	     : channel->timeout << query->itry / channel->nservers);
    }
}
Example #7
0
/* If any TCP sockets select true for writing, write out queued data
 * we have for them.
 */
static void write_tcp_data_core(ares_channel channel, int server_idx,
	time_t now)
{
  struct server_state *server;
  struct send_request *sendreq;
#ifdef WIN32
  WSABUF *vec;
#else
  struct iovec *vec;
#endif
  int n, count;

  server = &channel->servers[server_idx];
  if (!server->qhead || server->tcp_socket == -1 )
    return;

  /* Count the number of send queue items. */
  n = 0;
  for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
    n++;

#ifdef WIN32
  /* Allocate iovecs so we can send all our data at once. */
  vec = malloc(n * sizeof(WSABUF));
  if (vec)
    {
	    int err;
      /* Fill in the iovecs and send. */
      n = 0;
      for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
	{
	  vec[n].buf = (char *) sendreq->data;
	  vec[n].len = sendreq->len;
	  n++;
	}
      err = WSASend(server->tcp_socket, vec, n, &count,0,0,0 );
      if ( err == SOCKET_ERROR )
      {
	      count =-1;
      }
      free(vec);
#else
	 /* Allocate iovecs so we can send all our data at once. */
  vec = malloc(n * sizeof(struct iovec));
  if (vec)
    {
		    // int err;
      /* 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);
#endif

      if (count < 0)
	{
	  handle_error(channel, server_idx, now);
	  return;
	}

      /* 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;
	      free(sendreq);
	      if (server->qhead == NULL)
	      {
		server->qtail = NULL;
		assert(count==0);
		break;
	      }
	    }
	  else
	    {
	      sendreq->data += count;
	      sendreq->len -= count;
	      break;
	    }
	}
    }
  else
    {
      /* Can't allocate iovecs; just send the first request. */
      sendreq = server->qhead;
#ifndef UNDER_CE
      count = write(server->tcp_socket, sendreq->data, sendreq->len);
#else
      count = send(server->tcp_socket, sendreq->data, sendreq->len,0);
#endif
      if (count < 0)
	{
	  handle_error(channel, server_idx, now);
	  return;
	}

      /* 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 ( server->qhead==NULL && channel->poll_cb_func ) {
        (*(channel->poll_cb_func))( channel->poll_cb_data, channel, server_idx,
	  server->tcp_socket, ARES_POLLACTION_WRITEOFF);
    }
}


static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
{
  struct server_state *server;
  int i;

  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 )
        continue;
      if ( write_fds && !FD_ISSET(server->tcp_socket, write_fds))
	continue;

     write_tcp_data_core(channel, i, now);
  }
}

/* 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, int server_idx, 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. */
      if ( server_idx>=0 && i != server_idx )
         continue;
      server = &channel->servers[i];
      if (server->tcp_socket == -1 )
        continue;
      if (!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).
	   */
#if defined UNDER_CE || defined WIN32
      count = recv(server->tcp_socket,
                       server->tcp_lenbuf + server->tcp_lenbuf_pos,
                       2 - server->tcp_lenbuf_pos,0);
#else
      count = read(server->tcp_socket,
		       server->tcp_lenbuf + server->tcp_lenbuf_pos,
		       2 - server->tcp_lenbuf_pos);
#endif
	  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. */
#if defined UNDER_CE || defined WIN32
      count = recv(server->tcp_socket,
		       server->tcp_buffer + server->tcp_buffer_pos,
		       server->tcp_length - server->tcp_buffer_pos,0);
#else
      count = read(server->tcp_socket,
		       server->tcp_buffer + server->tcp_buffer_pos,
		       server->tcp_length - server->tcp_buffer_pos);
#endif

	  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, int server_idx,
			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++)
    {
      if ( server_idx>=0 && i != server_idx )
          continue;
      /* Make sure the server has a socket and is selected in read_fds. */
      server = &channel->servers[i];
      if ( (server->udp_socket == -1) )
          continue;
      if ( read_fds && !FD_ISSET(server->udp_socket, read_fds) )
	  continue;

	  assert( server->udp_socket != -1 );
	  
      count = recv(server->udp_socket, buf, sizeof(buf), 0);
      if (count <= 0)
	  {
#if defined(WIN32)
		//int err;
		//err = WSAGetLastError();
		//err = errno;
		switch (getErrno())
		{
		    case WSAEWOULDBLOCK:
			    if ( read_fds ) {
			       // read_fds is only null when using epoll
			       // which shouldn't happen under windows
			       // don't know why CLR is here anyways
			       FD_CLR(server->udp_socket, read_fds);
			    }
			    continue;
		    case WSAECONNABORTED:
			    break;
		    case WSAECONNRESET: // got an ICMP error on a previous send
			    break;
		}
#endif
		handle_error(channel, i, now);
	  }
	  else
	  {
		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)
	{
	  //fprintf(stderr, "kennard:ares:process_timeouts: got timeout\n");
	  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, time_t 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
   * with SERVFAIL, NOTIMP, or REFUSED response codes.
   */
  if (!(channel->flags & ARES_FLAG_NOCHECKRESP))
    {
      if (rcode == SERVFAIL || rcode == NOTIMP || rcode == REFUSED)
	{
	  query->skip_server[whichserver] = 1;
	  if (query->server == whichserver)
	    next_server(channel, query, now);
	  return;
	}
      if (!same_questions((unsigned char*)query->qbuf, query->qlen, abuf, alen))
	{
	  if (query->server == whichserver)
	    next_server(channel, query, now);
	  return;
	}

      /* 'No such name' */
      if ((channel->flags & ARES_FLAG_TRY_NEXT_SERVER_ON_RCODE3) && rcode == NXDOMAIN)
        {
          if (query->server == whichserver)
            {
              if (next_server_new_network(channel, query, now))
                return;
            }
        }
    }

  end_query(channel, query, ARES_SUCCESS, abuf, alen);
}