o Expose an ev_socklen_t type for consistent use across platforms.
o Make bufferevenr_socket_connect() work when the original fd was -1.
o Fix a bug in bufferevent_socket_connect() when the connection succeeds too quickly.
+ o Export an evutil_sockaddr_cmp() to compare to sockaddr objects for equality.
+
Changes in 2.0.2-alpha:
o Add a new flag to bufferevents to make all callbacks automatically deferred.
o Make evdns functionality locked, and automatically defer dns callbacks.
return "<unknown>";
}
-static int
-sockaddr_eq(const struct sockaddr *sa1, const struct sockaddr *sa2,
- int include_port)
-{
- if (sa1->sa_family != sa2->sa_family)
- return 0;
- if (sa1->sa_family == AF_INET) {
- const struct sockaddr_in *sin1, *sin2;
- sin1 = (const struct sockaddr_in *)sa1;
- sin2 = (const struct sockaddr_in *)sa2;
- if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr)
- return 0;
- else if (include_port && sin1->sin_port != sin2->sin_port)
- return 0;
- else
- return 1;
- }
-#ifdef AF_INET6
- if (sa1->sa_family == AF_INET6) {
- const struct sockaddr_in6 *sin1, *sin2;
- sin1 = (const struct sockaddr_in6 *)sa1;
- sin2 = (const struct sockaddr_in6 *)sa2;
- if (memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16))
- return 0;
- else if (include_port && sin1->sin6_port != sin2->sin6_port)
- return 0;
- else
- return 1;
- }
-#endif
- return 1;
-}
-
static evdns_debug_log_fn_type evdns_log_fn = NULL;
void
evutil_socket_error_to_string(err));
return;
}
- if (!sockaddr_eq((struct sockaddr*)&ss,
+ if (evutil_sockaddr_cmp((struct sockaddr*)&ss,
(struct sockaddr*)&ns->address, 0)) {
log(EVDNS_LOG_WARN, "Address mismatch on received "
"DNS packet. Apparent source was %s",
ASSERT_LOCKED(base);
if (server) {
do {
- if (sockaddr_eq((struct sockaddr*)&server->address, address, 1)) return 3;
+ if (!evutil_sockaddr_cmp((struct sockaddr*)&server->address, address, 1)) return 3;
server = server->next;
} while (server != started_at);
}
}
}
+int
+evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
+ int include_port)
+{
+ int r;
+ if (0 != (r = (sa1->sa_family - sa2->sa_family)))
+ return r;
+
+ if (sa1->sa_family == AF_INET) {
+ const struct sockaddr_in *sin1, *sin2;
+ sin1 = (const struct sockaddr_in *)sa1;
+ sin2 = (const struct sockaddr_in *)sa2;
+ if (sin1->sin_addr.s_addr < sin2->sin_addr.s_addr)
+ return -1;
+ else if (sin1->sin_addr.s_addr > sin2->sin_addr.s_addr)
+ return 1;
+ else if (include_port &&
+ (r = ((int)sin1->sin_port - (int)sin2->sin_port)))
+ return r;
+ else
+ return 0;
+ }
+#ifdef AF_INET6
+ else if (sa1->sa_family == AF_INET6) {
+ const struct sockaddr_in6 *sin1, *sin2;
+ sin1 = (const struct sockaddr_in6 *)sa1;
+ sin2 = (const struct sockaddr_in6 *)sa2;
+ if ((r = memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16)))
+ return r;
+ else if (include_port &&
+ (r = ((int)sin1->sin6_port - (int)sin2->sin6_port)))
+ return r;
+ else
+ return 0;
+ }
+#endif
+ return 1;
+}
+
/* Tables to implement ctypes-replacement EVUTIL_IS*() functions. Each table
* has 256 bits to look up whether a character is in some set or not. This
* fails on non-ASCII platforms, but so does every other place where we
*/
int evutil_parse_sockaddr_port(const char *str, struct sockaddr *out, int *outlen);
+/** Compare two sockaddrs; return 0 if they are equal, or less than 0 if sa1
+ * preceeds sa2, or greater than 0 if sa1 follows sa2. If include_port is
+ * true, consider the port as well as the address. Only implemented for
+ * AF_INET and AF_INET6 addresses. The ordering is not guaranteed to remain
+ * the same between Libevent versions. */
+int evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
+ int include_port);
+
/** As strcasecmp, but always compares the characters in locale-independent
ASCII. That's useful if you're handling data in ASCII-based protocols.
*/