/** Rate-limiting information for this bufferevent */
struct bufferevent_rate_limit *rate_limiting;
+
+ /* Saved conn_addr, to extract IP address from it.
+ *
+ * Because some servers may reset/close connection without waiting clients,
+ * in that case we can't extract IP address even in close_cb.
+ * So we need to save it, just after we connected to remote server, or
+ * after resolving (to avoid extra dns requests during retrying, since UDP
+ * is slow) */
+ struct sockaddr_storage *conn_address;
};
/** Possible operations for a control callback. */
enum bufferevent_options bufferevent_get_options_(struct bufferevent *bev);
+const struct sockaddr*
+bufferevent_socket_get_conn_address_(struct bufferevent *bev);
+
/** Internal use: We have just successfully read data into an inbuf, so
* reset the read timeout (if any). */
#define BEV_RESET_GENERIC_READ_TIMEOUT(bev) \
#define be_socket_add(ev, t) \
bufferevent_add_event_((ev), (t))
+const struct sockaddr*
+bufferevent_socket_get_conn_address_(struct bufferevent *bev)
+{
+ struct bufferevent_private *bev_p =
+ EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+
+ return (struct sockaddr *)bev_p->conn_address;
+}
+static void
+bufferevent_socket_set_conn_address_fd(struct bufferevent_private *bev_p, int fd)
+{
+ socklen_t len = sizeof(*bev_p->conn_address);
+
+ if (!bev_p->conn_address) {
+ bev_p->conn_address = mm_malloc(sizeof(*bev_p->conn_address));
+ }
+ if (getpeername(fd, (struct sockaddr *)bev_p->conn_address, &len)) {
+ mm_free(bev_p->conn_address);
+ bev_p->conn_address = NULL;
+ }
+}
+static void
+bufferevent_socket_set_conn_address(struct bufferevent_private *bev_p,
+ struct sockaddr *addr, size_t addrlen)
+{
+ if (!bev_p->conn_address) {
+ bev_p->conn_address = mm_malloc(sizeof(*bev_p->conn_address));
+ }
+ memcpy(bev_p->conn_address, addr, addrlen);
+}
+
static void
bufferevent_socket_outbuf_cb(struct evbuffer *buf,
const struct evbuffer_cb_info *cbinfo,
goto done;
} else {
connected = 1;
+ bufferevent_socket_set_conn_address_fd(bufev_p, fd);
#ifdef _WIN32
if (BEV_IS_ASYNC(bufev)) {
event_del(&bufev->ev_write);
/* XXX use the other addrinfos? */
/* XXX use this return value */
+ bufferevent_socket_set_conn_address(bev_p, ai->ai_addr, (int)ai->ai_addrlen);
r = bufferevent_socket_connect(bev, ai->ai_addr, (int)ai->ai_addrlen);
(void)r;
bufferevent_decref_and_unlock_(bev);
if ((bufev_p->options & BEV_OPT_CLOSE_ON_FREE) && fd >= 0)
EVUTIL_CLOSESOCKET(fd);
+
+ mm_free(bufev_p->conn_address);
+ bufev_p->conn_address = NULL;
}
static int
struct event_base *base;
struct evdns_base *dns_base;
int ai_family;
-
- /* Saved conn_addr, to extract IP address from it.
- *
- * Because some servers may reset/close connection without waiting clients,
- * in that case we can't extract IP address even in close_cb.
- * So we need to save it, just after we connected to remote server. */
- struct sockaddr_storage *conn_address;
};
/* A callback for an http server */
if (evcon->address != NULL)
mm_free(evcon->address);
- if (evcon->conn_address != NULL)
- mm_free(evcon->conn_address);
-
mm_free(evcon);
}
struct evhttp_connection *evcon = arg;
int error;
ev_socklen_t errsz = sizeof(error);
- socklen_t conn_address_len = sizeof(*evcon->conn_address);
if (evcon->fd == -1)
evcon->fd = bufferevent_getfd(bufev);
evcon->retry_cnt = 0;
evcon->state = EVCON_IDLE;
- if (!evcon->conn_address) {
- evcon->conn_address = mm_malloc(sizeof(*evcon->conn_address));
- }
- if (getpeername(evcon->fd, (struct sockaddr *)evcon->conn_address, &conn_address_len)) {
- mm_free(evcon->conn_address);
- evcon->conn_address = NULL;
- }
-
/* reset the bufferevent cbs */
bufferevent_setcb(evcon->bufev,
evhttp_read_cb,
const struct sockaddr*
evhttp_connection_get_addr(struct evhttp_connection *evcon)
{
- return (struct sockaddr *)evcon->conn_address;
+ return bufferevent_socket_get_conn_address_(evcon->bufev);
}
int
char **address, ev_uint16_t *port);
/** Get the remote address associated with this connection.
- * extracted from getpeername().
+ * extracted from getpeername() OR from nameserver.
*
* @return NULL if getpeername() return non success,
* or connection is not connected,