[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [obfsproxy/master] Don't set bufferevent callbacks before forming the circuit.
commit 4b754df88f8d658b4731ce93f2fcafcc34b72244
Author: George Kadianakis <desnacked@xxxxxxxxxx>
Date: Sat Mar 17 16:01:22 2012 -0700
Don't set bufferevent callbacks before forming the circuit.
Achieve that by splitting the circuit creation into three parts:
First, create the connection on the other side of the circuit. Then,
build the circuit. Finally, set up bufferevent callbacks.
Conflicts:
src/network.c
---
src/network.c | 151 +++++++++++++++++++++++++++------------------------------
1 files changed, 72 insertions(+), 79 deletions(-)
diff --git a/src/network.c b/src/network.c
index e42b195..219593f 100644
--- a/src/network.c
+++ b/src/network.c
@@ -150,7 +150,6 @@ static void conn_free_on_flush(struct bufferevent *bev, void *arg);
static void circuit_create_socks(conn_t *up);
static int circuit_add_down(circuit_t *circuit, conn_t *down);
static void circuit_free(circuit_t *circuit);
-static conn_t *open_outbound(conn_t *conn, bufferevent_data_cb readcb);
static void upstream_read_cb(struct bufferevent *bev, void *arg);
static void downstream_read_cb(struct bufferevent *bev, void *arg);
@@ -339,48 +338,63 @@ static int
conn_connect(conn_t *addr_conn, conn_t *connect_conn,
bufferevent_data_cb readcb)
{
- bufferevent_setcb(buf, readcb, NULL, pending_conn_cb, newconn);
+ char *peername;
+ struct evutil_addrinfo *addr = config_get_target_addr(addr_conn->cfg);
+ struct bufferevent *buf = connect_conn->buffer;
+
+ if (!addr) {
+ log_warn("%s: no target addresses available", safe_str(addr_conn->peername));
+ return -1;
+ }
+
+ bufferevent_setcb(buf, readcb, NULL, pending_conn_cb, connect_conn);
do {
peername = printable_address(addr->ai_addr, addr->ai_addrlen);
+
if (bufferevent_socket_connect(buf, addr->ai_addr, addr->ai_addrlen) >= 0)
goto success;
log_info("%s: connection to %s failed: %s",
- safe_str(conn->peername), safe_str(peername),
+ safe_str(addr_conn->peername), safe_str(peername),
evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
free(peername);
addr = addr->ai_next;
} while (addr);
log_warn("%s: all outbound connection attempts failed",
- conn->peername);
+ addr_conn->peername);
- conn_free(newconn);
- return NULL;
+ return -1;
success:
log_info("%s (%s): Successful outbound connection to '%s'.",
- safe_str(conn->peername), conn->cfg->vtable->name, safe_str(peername));
+ safe_str(addr_conn->peername),
+ addr_conn->cfg->vtable->name, safe_str(peername));
bufferevent_enable(buf, EV_READ|EV_WRITE);
- newconn->peername = peername;
- obfs_assert(connections);
- smartlist_add(connections, newconn);
+ connect_conn->peername = peername;
/* If we are a server, we should note this connection and consider
it in our heartbeat status messages. */
- if (conn->mode == LSN_SIMPLE_SERVER)
- status_note_connection(conn->peername);
+ if (addr_conn->mode == LSN_SIMPLE_SERVER)
+ status_note_connection(addr_conn->peername);
+
+ return 0;
}
/** Create the other side of connection <b>conn</b> on a circuit. */
static conn_t *
create_other_side_of_conn(const conn_t *conn)
{
+ struct event_base *base = bufferevent_get_base(conn->buffer);
+ struct bufferevent *buf;
+ conn_t *newconn;
+
buf = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
if (!buf) {
log_warn("%s: unable to create outbound socket buffer", safe_str(conn->peername));
return NULL;
}
+
newconn = proto_conn_create(conn->cfg);
if (!newconn) {
log_warn("%s: failed to allocate state for outbound connection",
@@ -391,6 +405,11 @@ create_other_side_of_conn(const conn_t *conn)
/* associate bufferevent with the new connection. */
newconn->buffer = buf;
+
+ obfs_assert(connections);
+ smartlist_add(connections, newconn);
+
+ return newconn;
}
/**
@@ -406,11 +425,22 @@ simple_client_listener_cb(conn_t *conn)
bufferevent_setcb(conn->buffer, upstream_read_cb, NULL, error_cb, conn);
- if (circuit_create(conn, open_outbound(conn, downstream_read_cb))) {
+ conn_t *newconn = create_other_side_of_conn(conn);
+ if (!newconn) {
+ conn_free(conn);
+ return;
+ }
+
+ if (circuit_create(conn, newconn)) {
conn_free(conn);
return;
}
+ if (conn_connect(conn, newconn, downstream_read_cb) < 0) {
+ conn_free(conn); /* circuit_free() should also free newconn. */
+ return;
+ }
+
log_debug("%s: setup complete", safe_str(conn->peername));
}
@@ -449,7 +479,18 @@ simple_server_listener_cb(conn_t *conn)
bufferevent_setcb(conn->buffer, downstream_read_cb, NULL, error_cb, conn);
- if (circuit_create(open_outbound(conn, upstream_read_cb), conn)) {
+ conn_t *newconn = create_other_side_of_conn(conn);
+ if (!newconn) {
+ conn_free(conn);
+ return;
+ }
+
+ if (circuit_create(newconn, conn)) {
+ conn_free(conn);
+ return;
+ }
+
+ if (conn_connect(conn, newconn, upstream_read_cb) < 0) {
conn_free(conn);
return;
}
@@ -560,61 +601,6 @@ circuit_free(circuit_t *circuit)
}
/**
- Make the outbound connection for a circuit.
-*/
-static conn_t *
-open_outbound(conn_t *conn, bufferevent_data_cb readcb)
-{
- struct evutil_addrinfo *addr = config_get_target_addr(conn->cfg);
- struct event_base *base = bufferevent_get_base(conn->buffer);
- struct bufferevent *buf;
- char *peername;
- conn_t *newconn;
-
- if (!addr) {
- log_warn("%s: no target addresses available", safe_str(conn->peername));
- return NULL;
- }
-
- buf = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
- if (!buf) {
- log_warn("%s: unable to create outbound socket buffer", safe_str(conn->peername));
- return NULL;
- }
-
- newconn = proto_conn_create(conn->cfg);
- if (!newconn) {
- log_warn("%s: failed to allocate state for outbound connection",
- safe_str(conn->peername));
- bufferevent_free(buf);
- return NULL;
- }
-
- newconn->buffer = buf;
-
- return newconn;
-}
-
-/**
- As open_outbound, but uses bufferevent_socket_connect_hostname
- rather than bufferevent_socket_connect.
-*/
-static conn_t *
-open_outbound_hostname(conn_t *conn, int af, const char *addr, uint16_t port)
-{
- struct event_base *base = bufferevent_get_base(conn->buffer);
- struct bufferevent *buf;
- conn_t *newconn;
-
- /* Set up a temporary FQDN peername. When we actually connect to the
- host, we will replace this peername with the IP address we
- connected to. */
- obfs_asprintf(&newconn->peername, "%s:%u", addr, port);
-
- return newconn;
-}
-
-/**
This callback is responsible for handling SOCKS traffic.
*/
static void
@@ -644,26 +630,33 @@ socks_read_cb(struct bufferevent *bev, void *arg)
log_info("%s: socks: trying to connect to %s:%u",
safe_str(conn->peername), safe_str(addr), port);
- if (circuit_add_down(conn->circuit,
- open_outbound_hostname(conn, af, addr, port))) {
+ conn_t *newconn = create_other_side_of_conn(conn);
+ if (!newconn) {
+ conn_free(conn);
+ return;
+ }
+
+ /* Set up a temporary FQDN peername. When we actually connect to the
+ host, we will replace this peername with the IP address we
+ connected to. */
+ obfs_asprintf(&newconn->peername, "%s:%u", addr, port);
+
+ if (circuit_add_down(conn->circuit, newconn)) {
/* XXXX send socks reply */
conn_free(conn);
return;
}
- bufferevent_setcb(buf, downstream_read_cb, NULL, pending_socks_cb, newconn);
- if (bufferevent_socket_connect_hostname(buf, get_evdns_base(),
+ bufferevent_setcb(newconn->buffer, downstream_read_cb, NULL, pending_socks_cb, newconn);
+ if (bufferevent_socket_connect_hostname(newconn->buffer, get_evdns_base(),
af, addr, port) < 0) {
log_warn("%s: outbound connection to %s:%u failed: %s",
safe_str(conn->peername), addr, port,
evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
- conn_free(newconn);
- return NULL;
+ conn_free(conn);
+ return;
}
-
- bufferevent_enable(buf, EV_READ|EV_WRITE);
- obfs_assert(connections);
- smartlist_add(connections, newconn);
+ bufferevent_enable(newconn->buffer, EV_READ|EV_WRITE);
/* further upstream data will be processed once the downstream
side is established */
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits