diff options
author | Nick Mathewson <nickm@torproject.org> | 2009-11-03 20:40:48 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2009-11-03 20:40:48 +0000 |
commit | 0b9eb1bffbd5af7d1dc6987f1a859e5f1e8c25e8 (patch) | |
tree | 5c41f0537d17c4bec064a8733c2093fef50624ed /bufferevent_sock.c | |
parent | fcc7668c008ce25d47834019c3d081819851c32d (diff) | |
download | libevent-0b9eb1bffbd5af7d1dc6987f1a859e5f1e8c25e8.tar.gz |
Add a bufferevent function to resolve a name then connect to it.
This function, bufferevent_socket_connect_hostname() can either use
evdns to do the resolve, or use a new function (evutil_resolve) that
uses getaddrinfo or gethostbyname, like http.c does now.
This function is meant to eventually replace the hostname resolution mess in
http.c.
svn:r1496
Diffstat (limited to 'bufferevent_sock.c')
-rw-r--r-- | bufferevent_sock.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/bufferevent_sock.c b/bufferevent_sock.c index 2cfef385..11dd10d3 100644 --- a/bufferevent_sock.c +++ b/bufferevent_sock.c @@ -54,6 +54,12 @@ #ifdef _EVENT_HAVE_SYS_SOCKET_H #include <sys/socket.h> #endif +#ifdef _EVENT_HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef _EVENT_HAVE_NETINET_IN6_H +#include <netinet/in6.h> +#endif #include "event2/util.h" #include "event2/bufferevent.h" @@ -352,6 +358,73 @@ done: return result; } +static int (*_bufferevent_socket_connect_hostname_evdns_fn)( + struct bufferevent *, struct evdns_base *, int, + const char *, int) = NULL; + +void _bufferevent_set_socket_connect_hostname_evdns_fn( + int (*fn)(struct bufferevent *, struct evdns_base *, int, + const char *, int)) +{ + if (!_bufferevent_socket_connect_hostname_evdns_fn) + _bufferevent_socket_connect_hostname_evdns_fn = fn; +} + +int +bufferevent_socket_connect_hostname(struct bufferevent *bev, + struct evdns_base *evdns_base, int family, const char *hostname, int port) +{ + struct sockaddr_storage ss; + ev_socklen_t socklen = sizeof(ss); + int socklen_int = sizeof(ss); + + if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC) + return -1; + if (port < 1 || port > 65535) + return -1; + + memset(&ss, 0, sizeof(ss)); + if (!evutil_parse_sockaddr_port(hostname, (struct sockaddr*)&ss, + &socklen_int)) { + socklen = socklen_int; + if (ss.ss_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in*)&ss; + if (family == AF_INET6) + return -1; + if (sin->sin_port) + return -1; + sin->sin_port = htons(port); + } else if (ss.ss_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&ss; + if (family == AF_INET) + return -1; + if (sin6->sin6_port) + return -1; + sin6->sin6_port = htons(port); + } + return bufferevent_socket_connect(bev, (struct sockaddr*)&ss, + socklen); + } + + if (evdns_base) { + EVUTIL_ASSERT(_bufferevent_socket_connect_hostname_evdns_fn); + return _bufferevent_socket_connect_hostname_evdns_fn( + bev, evdns_base, family, hostname, port); + } + + memset(&ss, 0, sizeof(ss)); + + if (evutil_resolve(family, hostname, (struct sockaddr*)&ss, + &socklen, port)<0) { + _bufferevent_incref_and_lock(bev); + _bufferevent_run_eventcb(bev, BEV_EVENT_ERROR); + _bufferevent_decref_and_unlock(bev); + return -1; + } + + return bufferevent_socket_connect(bev, (struct sockaddr*)&ss, socklen); +} + /* * Create a new buffered event object. * |