Blame view

3rdparty/c-ares-1.18.1/src/lib/ares_timeout.c 2.68 KB
73ef4ff3   Hu Chunming   提交三方库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  
  /* 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.
   */
  
  #include "ares_setup.h"
  
  #ifdef HAVE_LIMITS_H
  #include <limits.h>
  #endif
  
  #include "ares.h"
  #include "ares_private.h"
  
  /* return time offset between now and (future) check, in milliseconds */
  static long timeoffset(struct timeval *now, struct timeval *check)
  {
    return (check->tv_sec - now->tv_sec)*1000 +
           (check->tv_usec - now->tv_usec)/1000;
  }
  
  /* WARNING: Beware that this is linear in the number of outstanding
   * requests! You are probably far better off just calling ares_process()
   * once per second, rather than calling ares_timeout() to figure out
   * when to next call ares_process().
   */
  struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv,
                               struct timeval *tvbuf)
  {
    struct query *query;
    struct list_node* list_head;
    struct list_node* list_node;
    struct timeval now;
    struct timeval nextstop;
    long offset, min_offset;
  
    /* No queries, no timeout (and no fetch of the current time). */
    if (ares__is_list_empty(&(channel->all_queries)))
      return maxtv;
  
    /* Find the minimum timeout for the current set of queries. */
    now = ares__tvnow();
    min_offset = -1;
  
    list_head = &(channel->all_queries);
    for (list_node = list_head->next; list_node != list_head;
         list_node = list_node->next)
      {
        query = list_node->data;
        if (query->timeout.tv_sec == 0)
          continue;
        offset = timeoffset(&now, &query->timeout);
        if (offset < 0)
          offset = 0;
        if (min_offset == -1 || offset < min_offset)
          min_offset = offset;
      }
  
    /* If we found a minimum timeout and it's sooner than the one specified in
     * maxtv (if any), return it.  Otherwise go with maxtv.
     */
    if (min_offset != -1)
      {
        int ioffset = (min_offset > (long)INT_MAX) ? INT_MAX : (int)min_offset;
  
        nextstop.tv_sec = ioffset/1000;
        nextstop.tv_usec = (ioffset%1000)*1000;
  
        if (!maxtv || ares__timedout(maxtv, &nextstop))
          {
            *tvbuf = nextstop;
            return tvbuf;
          }
      }
  
    return maxtv;
  }