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
ares__timeval_remaining(struct timeval * remaining,const struct timeval * now,const struct timeval * tout)37 void 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
ares_timeout(ares_channel_t * channel,struct timeval * maxtv,struct timeval * tvbuf)58 struct 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