Commit d426c20c authored by Steinar H. Gunderson's avatar Steinar H. Gunderson
Browse files

Three fixes in one commit (sorry): a) Take care of the tcpbuf if it ends while...

Three fixes in one commit (sorry): a) Take care of the tcpbuf if it ends while queued for transmission, note broken servers and close them in the main loop, and store TCP socket generation number in order not to send the same query twice over the same socket.
parent 54ca7d8c
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ void ares__close_sockets(ares_channel channel, struct server_state *server)
      /* Advance server->qhead; pull out query as we go. */
      sendreq = server->qhead;
      server->qhead = sendreq->next;
      if (sendreq->data_storage != NULL)
        free(sendreq->data_storage);
      free(sendreq);
    }
  server->qtail = NULL;
@@ -45,12 +47,16 @@ void ares__close_sockets(ares_channel channel, struct server_state *server)
  server->tcp_buffer = NULL;
  server->tcp_lenbuf_pos = 0;

  /* Reset brokenness */
  server->is_broken = 0;

  /* Close the TCP and UDP sockets. */
  if (server->tcp_socket != ARES_SOCKET_BAD)
    {
      SOCK_STATE_CALLBACK(channel, server->tcp_socket, 0, 0);
      closesocket(server->tcp_socket);
      server->tcp_socket = ARES_SOCKET_BAD;
      server->tcp_connection_generation = ++channel->tcp_connection_generation;
    }
  if (server->udp_socket != ARES_SOCKET_BAD)
    {
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ void ares_cancel(ares_channel channel)
    next = query->next;
    query->callback(query->arg, ARES_ETIMEOUT, NULL, 0);
    free(query->tcpbuf);
    free(query->skip_server);
    free(query->server_info);
    free(query);
  }
  channel->queries = NULL;
+2 −2
Original line number Diff line number Diff line
@@ -65,8 +65,8 @@ void ares_destroy(ares_channel channel)
    query->callback(query->arg, ARES_EDESTRUCTION, NULL, 0);
    if (query->tcpbuf)
      free(query->tcpbuf);
    if (query->skip_server)
      free(query->skip_server);
    if (query->server_info)
      free(query->server_info);
    free(query);
  }

+3 −0
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
  channel->nservers = -1;
  channel->ndomains = -1;
  channel->nsort = -1;
  channel->tcp_connection_generation = 0;
  channel->lookups = NULL;
  channel->queries = NULL;
  channel->domains = NULL;
@@ -201,10 +202,12 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
      server = &channel->servers[i];
      server->udp_socket = ARES_SOCKET_BAD;
      server->tcp_socket = ARES_SOCKET_BAD;
      server->tcp_connection_generation = ++channel->tcp_connection_generation;
      server->tcp_lenbuf_pos = 0;
      server->tcp_buffer = NULL;
      server->qhead = NULL;
      server->qtail = NULL;
      server->is_broken = 0;
    }

  init_id_key(&channel->id_key, ARES_ID_KEY_LEN);
+26 −2
Original line number Diff line number Diff line
@@ -89,6 +89,11 @@ struct send_request {
  const unsigned char *data;
  size_t len;

  /* The query for which we're sending this data */
  struct query* owner_query;
  /* The buffer we're using, if we have our own copy of the packet */
  unsigned char *data_storage;

  /* Next request in queue */
  struct send_request *next;
};
@@ -110,6 +115,17 @@ struct server_state {
  /* TCP output queue */
  struct send_request *qhead;
  struct send_request *qtail;

  /* Which incarnation of this connection is this? We don't want to
   * retransmit requests into the very same socket, but if the server
   * closes on us and we re-open the connection, then we do want to
   * re-send. */
  int tcp_connection_generation;

  /* Is this server broken? We mark connections as broken when a
   * request that is queued for sending times out.
   */
  int is_broken;
};

struct query {
@@ -130,7 +146,7 @@ struct query {
  /* Query status */
  int try;
  int server;
  int *skip_server;
  struct query_server_info *server_info;   /* per-server state */
  int using_tcp;
  int error_status;

@@ -138,6 +154,12 @@ struct query {
  struct query *next;
};

/* Per-server state for a query */
struct query_server_info {
  int skip_server;  /* should we skip server, due to errors, etc? */
  int tcp_connection_generation;  /* into which TCP connection did we send? */
};

/* An IP address pattern; matches an IP address X if X & mask == addr */
#define PATTERN_MASK 0x1
#define PATTERN_CIDR 0x2
@@ -188,6 +210,9 @@ struct ares_channeldata {
  /* key to use when generating new ids */
  rc4_key id_key;

  /* Generation number to use for the next TCP socket open/close */
  int tcp_connection_generation;

  /* Active queries */
  struct query *queries;

@@ -220,4 +245,3 @@ short ares__generate_new_id(rc4_key* key);
#endif

#endif /* __ARES_PRIVATE_H */
Loading