mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 13:04:23 -04:00
http: implement new evhttp_connection_get_addr() api.
Basically tcp final handshake looks like this: (C - client, S - server) ACK[C] - FIN/ACK[S] - FIN/ACK[S] - ACK [C] However there are servers, that didn't close connection like this, while it is still _considered_ as valid, and using libevent http layer we can do requests to such servers. Modified handshake: (C - client, S - server) ACK[C] - RST/ACK[S] - RST/ACK[S] And in this case we can't extract IP address from socket, because it is already closed, and getpeername() will return: "transport endpoint is not connected". So we need to store address that we are connecting to, after we know it, and that is what this patch do. I have reproduced it, however it have some extra packages. (I will try to fix it) https://github.com/azat/nfq-examples/blob/master/nfqnl_rst_fin.c
This commit is contained in:
parent
4464bd2396
commit
0c7f0405e3
@ -99,6 +99,13 @@ struct evhttp_connection {
|
||||
|
||||
struct event_base *base;
|
||||
struct evdns_base *dns_base;
|
||||
|
||||
/* 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 */
|
||||
|
18
http.c
18
http.c
@ -1168,6 +1168,9 @@ evhttp_connection_free(struct evhttp_connection *evcon)
|
||||
if (evcon->address != NULL)
|
||||
mm_free(evcon->address);
|
||||
|
||||
if (evcon->conn_address != NULL)
|
||||
mm_free(evcon->conn_address);
|
||||
|
||||
mm_free(evcon);
|
||||
}
|
||||
|
||||
@ -1404,6 +1407,7 @@ evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
|
||||
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);
|
||||
@ -1454,6 +1458,14 @@ evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
|
||||
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,
|
||||
@ -2348,6 +2360,12 @@ evhttp_connection_get_peer(struct evhttp_connection *evcon,
|
||||
*port = evcon->port;
|
||||
}
|
||||
|
||||
const struct sockaddr*
|
||||
evhttp_connection_get_addr(struct evhttp_connection *evcon)
|
||||
{
|
||||
return (struct sockaddr *)evcon->conn_address;
|
||||
}
|
||||
|
||||
int
|
||||
evhttp_connection_connect_(struct evhttp_connection *evcon)
|
||||
{
|
||||
|
@ -614,6 +614,15 @@ void evhttp_connection_set_closecb(struct evhttp_connection *evcon,
|
||||
void evhttp_connection_get_peer(struct evhttp_connection *evcon,
|
||||
char **address, ev_uint16_t *port);
|
||||
|
||||
/** Get the remote address associated with this connection.
|
||||
* extracted from getpeername().
|
||||
*
|
||||
* @return NULL if getpeername() return non success,
|
||||
* or connection is not connected,
|
||||
* otherwise it return pointer to struct sockaddr_storage */
|
||||
const struct sockaddr*
|
||||
evhttp_connection_get_addr(struct evhttp_connection *evcon);
|
||||
|
||||
/**
|
||||
Make an HTTP request over the specified connection.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user