2 * General utility functions which don't have better places to live.
7 #include <sys/socket.h>
17 * Calculate the difference between two timevals.
18 * Lifted wholesale from the GNU libc manual.
21 timeval_diff(struct timeval
*result
, struct timeval
*x
, struct timeval
*y
)
23 /* Perform the carry for the later subtraction by updating y. */
24 if (x
->tv_usec
< y
->tv_usec
) {
25 int nsec
= (y
->tv_usec
- x
->tv_usec
) / 1000000 + 1;
26 y
->tv_usec
-= 1000000 * nsec
;
29 if (x
->tv_usec
- y
->tv_usec
> 1000000) {
30 int nsec
= (x
->tv_usec
- y
->tv_usec
) / 1000000;
31 y
->tv_usec
+= 1000000 * nsec
;
35 /* Compute the time remaining to wait.
36 tv_usec is certainly positive. */
37 result
->tv_sec
= x
->tv_sec
- y
->tv_sec
;
38 result
->tv_usec
= x
->tv_usec
- y
->tv_usec
;
40 /* Return 1 if result is negative. */
41 return x
->tv_sec
< y
->tv_sec
;
45 * Increment one timeval by another.
48 timeval_increment(struct timeval
*result
, struct timeval
*diff
)
50 const long u_factor
= 1000000;
52 result
->tv_sec
+= diff
->tv_sec
;
53 result
->tv_usec
+= diff
->tv_usec
;
54 if (result
->tv_usec
< 0) {
55 result
->tv_usec
+= u_factor
;
57 } else if (result
->tv_usec
> u_factor
) {
58 result
->tv_usec
-= u_factor
;
63 /** string_to_addrinfo_call
64 * Attempt to parse a sockaddr ip and port out of a string,
65 * calls ai_cb function with result (until one success, or
66 * for all results depending on flag values).
68 * IPv6 addresses must be [bracketed]. (Because of colons.)
76 #define _CB_ITER_ALL (1<<0)
78 string_to_addrinfo_call(char *in
, unsigned int flags
, int (*ai_cb
)(struct addrinfo
*, void *), void *cb_data
)
80 char *full_string
, *port_start
, *addr_start
, *tmp
;
81 struct addrinfo hints
, *res
=NULL
, *res_iter
;
84 full_string
= strdup(in
);
86 NOTIFY_ERROR("%s:%s", "strdup", strerror(errno
) );
90 addr_start
= strchr(full_string
, '[');
93 tmp
= strchr(addr_start
, ']');
95 NOTIFY_ERROR("invalid %saddress '%s': %s", "IPv6 ", in
, "unmatched brackets");
102 addr_start
= full_string
;
103 port_start
= addr_start
;
106 tmp
= strrchr(port_start
, ':');
108 NOTIFY_ERROR("invalid %saddress '%s': %s", "", in
, "no port specified");
115 /* We now have address and port as separate strings */
117 memset(&hints
, 0, sizeof hints
);
119 hints
.ai_family
= AF_UNSPEC
;
120 hints
.ai_socktype
= SOCK_STREAM
;
122 /* bind to equiv of INADDR_ANY for any AF, if address is specified as '*' */
123 if (strcmp(addr_start
, "*") == 0) {
124 hints
.ai_flags
|= AI_PASSIVE
;
128 r
= getaddrinfo(addr_start
, port_start
, &hints
, &res
);
130 NOTIFY_ERROR("%s:%s", "getaddrinfo", gai_strerror(r
));
135 for (res_iter
= res
; res_iter
; res_iter
= res_iter
->ai_next
) {
136 r
= ai_cb(res_iter
, cb_data
);
138 NOTIFY_DEBUG("%s:%d", "(ai_cb)", r
);
142 if (! (flags
& _CB_ITER_ALL
)) {