1/* MIT License
2 *
3 * Copyright (c) 1998 Massachusetts Institute of Technology
4 * Copyright (c) The c-ares project and its contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * SPDX-License-Identifier: MIT
26 */
27
28#include "ares_setup.h"
29
30#ifdef HAVE_LIMITS_H
31#  include <limits.h>
32#endif
33
34#include "ares.h"
35#include "ares_private.h"
36
37void ares__timeval_remaining(struct timeval       *remaining,
38                             const struct timeval *now,
39                             const struct timeval *tout)
40{
41  memset(remaining, 0, sizeof(*remaining));
42
43  /* Expired! */
44  if (tout->tv_sec < now->tv_sec ||
45      (tout->tv_sec == now->tv_sec && tout->tv_usec < now->tv_usec)) {
46    return;
47  }
48
49  remaining->tv_sec = tout->tv_sec - now->tv_sec;
50  if (tout->tv_usec < now->tv_usec) {
51    remaining->tv_sec  -= 1;
52    remaining->tv_usec  = (tout->tv_usec + 1000000) - now->tv_usec;
53  } else {
54    remaining->tv_usec = tout->tv_usec - now->tv_usec;
55  }
56}
57
58struct timeval *ares_timeout(ares_channel_t *channel, struct timeval *maxtv,
59                             struct timeval *tvbuf)
60{
61  const struct query *query;
62  ares__slist_node_t *node;
63  struct timeval      now;
64
65  /* The minimum timeout of all queries is always the first entry in
66   * channel->queries_by_timeout */
67  node = ares__slist_node_first(channel->queries_by_timeout);
68  /* no queries/timeout */
69  if (node == NULL) {
70    return maxtv; /* <-- maxtv can be null though, hrm */
71  }
72
73  query = ares__slist_node_val(node);
74
75  now = ares__tvnow();
76
77  ares__timeval_remaining(tvbuf, &now, &query->timeout);
78
79  if (maxtv == NULL) {
80    return tvbuf;
81  }
82
83  /* Return the minimum time between maxtv and tvbuf */
84
85  if (tvbuf->tv_sec > maxtv->tv_sec) {
86    return maxtv;
87  }
88  if (tvbuf->tv_sec < maxtv->tv_sec) {
89    return tvbuf;
90  }
91
92  if (tvbuf->tv_usec > maxtv->tv_usec) {
93    return maxtv;
94  }
95
96  return tvbuf;
97}
98