aboutsummaryrefslogtreecommitdiff
path: root/src/or/connection.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2004-05-12 19:17:09 +0000
committerNick Mathewson <nickm@torproject.org>2004-05-12 19:17:09 +0000
commitf1bc7af9f54bb4b563ffa024b1e32a6acacef26f (patch)
tree45bfe6288f7d804617795d79fd48049726e6dada /src/or/connection.c
parent4c9138d6406285077c3fc527f181610cd81b5727 (diff)
downloadtor-f1bc7af9f54bb4b563ffa024b1e32a6acacef26f.tar
tor-f1bc7af9f54bb4b563ffa024b1e32a6acacef26f.tar.gz
Make "connected" a different case from "finished_flushing"; always close_immediate whhen connect() fails.
svn:r1852
Diffstat (limited to 'src/or/connection.c')
-rw-r--r--src/or/connection.c71
1 files changed, 67 insertions, 4 deletions
diff --git a/src/or/connection.c b/src/or/connection.c
index b1ae7dc4c..b95a40850 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -77,6 +77,8 @@ char *conn_state_to_string[][_CONN_TYPE_MAX+1] = {
static int connection_init_accepted_conn(connection_t *conn);
static int connection_handle_listener_read(connection_t *conn, int new_type);
static int connection_receiver_bucket_should_increase(connection_t *conn);
+static int connection_finished_flushing(connection_t *conn);
+static int connection_finished_connecting(connection_t *conn);
/**************************************************************/
@@ -775,13 +777,34 @@ int connection_outbuf_too_full(connection_t *conn) {
* return 0.
*/
int connection_handle_write(connection_t *conn) {
+ int e, len=sizeof(e);
tor_assert(!connection_is_listener(conn));
conn->timestamp_lastwritten = time(NULL);
- if (connection_speaks_cells(conn) &&
- conn->state != OR_CONN_STATE_CONNECTING) {
+ /* Sometimes, "writeable" means "connected". */
+ if (connection_state_is_connecting(conn)) {
+ if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) {
+ /* not yet */
+ if(!ERRNO_IS_CONN_EINPROGRESS(tor_socket_errno(conn->s))) {
+ log_fn(LOG_DEBUG,"in-progress connect failed. Removing.");
+ /* The reason here only applies to exit connections, but it's
+ * harmless to set it elsewhere. */
+ connection_close_immediate(conn);
+ connection_mark_for_close(conn,END_STREAM_REASON_CONNECTFAILED);
+ if (conn->nickname)
+ router_mark_as_down(conn->nickname);
+ return -1;
+ } else {
+ return 0; /* no change, see if next time is better */
+ }
+ }
+ /* The connection is successful. */
+ return connection_finished_connecting(conn);
+ }
+
+ if (connection_speaks_cells(conn)) {
if (conn->state == OR_CONN_STATE_HANDSHAKING) {
connection_stop_writing(conn);
if(connection_tls_continue_handshake(conn) < 0) {
@@ -827,7 +850,6 @@ int connection_handle_write(connection_t *conn) {
connection_mark_for_close(conn, END_STREAM_REASON_MISC);
return -1;
}
- /* conns in CONNECTING state will fall through... */
}
if(!connection_wants_to_flush(conn)) /* it's done flushing */
@@ -1031,6 +1053,24 @@ int connection_state_is_open(connection_t *conn) {
return 0;
}
+int connection_state_is_connecting(connection_t *conn) {
+ tor_assert(conn);
+
+ if (conn->marked_for_close)
+ return 0;
+ switch (conn->type)
+ {
+ case CONN_TYPE_OR:
+ return conn->state == OR_CONN_STATE_CONNECTING;
+ case CONN_TYPE_EXIT:
+ return conn->state == EXIT_CONN_STATE_CONNECTING;
+ case CONN_TYPE_DIR:
+ return conn->state == DIR_CONN_STATE_CONNECTING;
+ }
+
+ return 0;
+}
+
/** Write a destroy cell with circ ID <b>circ_id</b> onto OR connection
* <b>conn</b>.
*
@@ -1083,7 +1123,7 @@ int connection_process_inbuf(connection_t *conn) {
* This function just passes conn to the connection-specific
* connection_*_finished_flushing() function.
*/
-int connection_finished_flushing(connection_t *conn) {
+static int connection_finished_flushing(connection_t *conn) {
tor_assert(conn);
@@ -1107,6 +1147,29 @@ int connection_finished_flushing(connection_t *conn) {
}
}
+/** Called when our attempt to connect() to another server has just
+ * succeeded.
+ *
+ * This function just passes conn to the connection-specific
+ * connection_*_finished_connecting() function.
+ */
+static int connection_finished_connecting(connection_t *conn)
+{
+ tor_assert(conn);
+ switch (conn->type)
+ {
+ case CONN_TYPE_OR:
+ return connection_or_finished_connecting(conn);
+ case CONN_TYPE_EXIT:
+ return connection_edge_finished_connecting(conn);
+ case CONN_TYPE_DIR:
+ return connection_dir_finished_connecting(conn);
+ default:
+ tor_assert(0);
+ return -1;
+ }
+}
+
/** Verify that connection <b>conn</b> has all of its invariants
* correct. Trigger an assert if anything is invalid.
*/