[or-cvs] Make "connected" a different case from "finished_flushing";...
Nick Mathewson
nickm at seul.org
Wed May 12 19:17:12 UTC 2004
Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv25130/src/or
Modified Files:
connection.c connection_edge.c connection_or.c directory.c
or.h
Log Message:
Make "connected" a different case from "finished_flushing"; always close_immediate whhen connect() fails.
Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection.c,v
retrieving revision 1.218
retrieving revision 1.219
diff -u -d -r1.218 -r1.219
--- connection.c 10 May 2004 10:27:54 -0000 1.218
+++ connection.c 12 May 2004 19:17:09 -0000 1.219
@@ -77,6 +77,8 @@
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 @@
* 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 @@
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 @@
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 @@
* 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 @@
}
}
+/** 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.
*/
Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_edge.c,v
retrieving revision 1.186
retrieving revision 1.187
diff -u -d -r1.186 -r1.187
--- connection_edge.c 10 May 2004 10:27:54 -0000 1.186
+++ connection_edge.c 12 May 2004 19:17:09 -0000 1.187
@@ -534,10 +534,6 @@
/** Connection <b>conn</b> has finished writing and has no bytes left on
* its outbuf.
*
- * If it's in state 'connecting', then take a look at the socket, and
- * take appropriate actions (such as sending back a relay 'connected'
- * cell) if the connect succeeded.
- *
* If it's in state 'open', stop writing, consider responding with a
* sendme, and return.
* Otherwise, stop writing and return.
@@ -546,47 +542,10 @@
* return 0.
*/
int connection_edge_finished_flushing(connection_t *conn) {
- unsigned char connected_payload[4];
- int e, len=sizeof(e);
-
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_AP || conn->type == CONN_TYPE_EXIT);
switch(conn->state) {
- case EXIT_CONN_STATE_CONNECTING:
- if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) { /* not yet */
- if(!ERRNO_IS_CONN_EINPROGRESS(tor_socket_errno(conn->s))) {
- /* yuck. kill it. */
- log_fn(LOG_DEBUG,"in-progress exit connect failed. Removing.");
- connection_mark_for_close(conn, END_STREAM_REASON_CONNECTFAILED);
- return -1;
- } else {
- log_fn(LOG_DEBUG,"in-progress exit connect still waiting.");
- return 0; /* no change, see if next time is better */
- }
- }
- /* the connect has finished. */
-
- log_fn(LOG_INFO,"Exit connection to %s:%u established.",
- conn->address,conn->port);
-
- conn->state = EXIT_CONN_STATE_OPEN;
- connection_watch_events(conn, POLLIN); /* stop writing, continue reading */
- if(connection_wants_to_flush(conn)) /* in case there are any queued relay cells */
- connection_start_writing(conn);
- /* deliver a 'connected' relay cell back through the circuit. */
- if(connection_edge_is_rendezvous_stream(conn)) {
- if(connection_edge_send_command(conn, circuit_get_by_conn(conn),
- RELAY_COMMAND_CONNECTED, NULL, 0, conn->cpath_layer) < 0)
- return 0; /* circuit is closed, don't continue */
- } else {
- *(uint32_t*)connected_payload = htonl(conn->addr);
- if(connection_edge_send_command(conn, circuit_get_by_conn(conn),
- RELAY_COMMAND_CONNECTED, connected_payload, 4, conn->cpath_layer) < 0)
- return 0; /* circuit is closed, don't continue */
- }
- tor_assert(conn->package_window > 0);
- return connection_edge_process_inbuf(conn); /* in case the server has written anything */
case AP_CONN_STATE_OPEN:
case EXIT_CONN_STATE_OPEN:
connection_stop_writing(conn);
@@ -605,6 +564,40 @@
return 0;
}
+/** Connected handler for exit connections: start writing pending
+ * data, deliver 'CONNECTED' relay cells as appropriate, and check
+ * any pending data that may have been received. */
+int connection_edge_finished_connecting(connection_t *conn)
+{
+ unsigned char connected_payload[4];
+
+ tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_EXIT);
+ tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING);
+
+
+ log_fn(LOG_INFO,"Exit connection to %s:%u established.",
+ conn->address,conn->port);
+
+ conn->state = EXIT_CONN_STATE_OPEN;
+ connection_watch_events(conn, POLLIN); /* stop writing, continue reading */
+ if(connection_wants_to_flush(conn)) /* in case there are any queued relay cells */
+ connection_start_writing(conn);
+ /* deliver a 'connected' relay cell back through the circuit. */
+ if(connection_edge_is_rendezvous_stream(conn)) {
+ if(connection_edge_send_command(conn, circuit_get_by_conn(conn),
+ RELAY_COMMAND_CONNECTED, NULL, 0, conn->cpath_layer) < 0)
+ return 0; /* circuit is closed, don't continue */
+ } else {
+ *(uint32_t*)connected_payload = htonl(conn->addr);
+ if(connection_edge_send_command(conn, circuit_get_by_conn(conn),
+ RELAY_COMMAND_CONNECTED, connected_payload, 4, conn->cpath_layer) < 0)
+ return 0; /* circuit is closed, don't continue */
+ }
+ tor_assert(conn->package_window > 0);
+ return connection_edge_process_inbuf(conn); /* in case the server has written anything */
+}
+
uint64_t stats_n_data_cells_packaged = 0;
uint64_t stats_n_data_bytes_packaged = 0;
uint64_t stats_n_data_cells_received = 0;
Index: connection_or.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_or.c,v
retrieving revision 1.106
retrieving revision 1.107
diff -u -d -r1.106 -r1.107
--- connection_or.c 10 May 2004 04:34:48 -0000 1.106
+++ connection_or.c 12 May 2004 19:17:09 -0000 1.107
@@ -59,50 +59,41 @@
/** Connection <b>conn</b> has finished writing and has no bytes left on
* its outbuf.
*
- * If it's in state "connecting", then take a look at the socket, and
- * begin the tls handshake if the connect succeeded.
- *
* Otherwise it's in state "open": stop writing and return.
*
* If <b>conn</b> is broken, mark it for close and return -1, else
* return 0.
*/
int connection_or_finished_flushing(connection_t *conn) {
- int e, len=sizeof(e);
-
tor_assert(conn && conn->type == CONN_TYPE_OR);
+
assert_connection_ok(conn,0);
- switch(conn->state) {
- case OR_CONN_STATE_CONNECTING:
- 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.");
- connection_mark_for_close(conn,0);
- return -1;
- } else {
- return 0; /* no change, see if next time is better */
- }
- }
- /* the connect has finished. */
+ if (conn->state != OR_CONN_STATE_OPEN) {
+ log_fn(LOG_WARN,"BUG: called in unexpected state %d",conn->state);
+ return -1;
+ }
- log_fn(LOG_INFO,"OR connect() to router %s:%u finished.",
- conn->address,conn->port);
+ connection_stop_writing(conn);
+ return 0;
+}
- if(connection_tls_start_handshake(conn, 0) < 0) {
- /* TLS handhaking error of some kind. */
- connection_mark_for_close(conn,0);
- return -1;
- }
- return 0;
- case OR_CONN_STATE_OPEN:
- connection_stop_writing(conn);
- return 0;
- default:
- log_fn(LOG_WARN,"BUG: called in unexpected state %d",conn->state);
- return 0;
+/** Connected handler for OR connections: begin the TLS handshake.
+ */
+int connection_or_finished_connecting(connection_t *conn)
+{
+ tor_assert(conn && conn->type == CONN_TYPE_OR);
+ tor_assert(conn->state == OR_CONN_STATE_CONNECTING);
+
+ log_fn(LOG_INFO,"OR connect() to router %s:%u finished.",
+ conn->address,conn->port);
+
+ if(connection_tls_start_handshake(conn, 0) < 0) {
+ /* TLS handhaking error of some kind. */
+ connection_mark_for_close(conn,0);
+ return -1;
}
+ return 0;
}
/** Initialize <b>conn</b> to include all the relevant data from <b>router</b>.
Index: directory.c
===================================================================
RCS file: /home/or/cvsroot/src/or/directory.c,v
retrieving revision 1.101
retrieving revision 1.102
diff -u -d -r1.101 -r1.102
--- directory.c 10 May 2004 04:34:48 -0000 1.101
+++ directory.c 12 May 2004 19:17:09 -0000 1.102
@@ -523,8 +523,8 @@
}
/** Write handler for directory connections; called when all data has
- * been flushed. Handle a completed connection: close the connection
- * or wait for a response as appropriate.
+ * been flushed. Close the connection or wait for a response as
+ * appropriate.
*/
int connection_dir_finished_flushing(connection_t *conn) {
int e, len=sizeof(e);
@@ -532,24 +532,6 @@
tor_assert(conn && conn->type == CONN_TYPE_DIR);
switch(conn->state) {
- case DIR_CONN_STATE_CONNECTING:
- 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.");
- router_mark_as_down(conn->nickname); /* don't try him again */
- connection_mark_for_close(conn,0);
- return -1;
- } else {
- return 0; /* no change, see if next time is better */
- }
- }
- /* the connect has finished. */
-
- log_fn(LOG_INFO,"Dir connection to router %s:%u established.",
- conn->address,conn->port);
-
- conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
- return 0;
case DIR_CONN_STATE_CLIENT_SENDING:
log_fn(LOG_DEBUG,"client finished sending command.");
conn->state = DIR_CONN_STATE_CLIENT_READING;
@@ -566,6 +548,20 @@
return 0;
}
+/** Connected handler for directory connections: begin sending data to the
+ * server */
+int connection_dir_finished_connecting(connection_t *conn)
+{
+ tor_assert(conn && conn->type == CONN_TYPE_DIR);
+ tor_assert(conn->state == DIR_CONN_STATE_CONNECTING);
+
+ log_fn(LOG_INFO,"Dir connection to router %s:%u established.",
+ conn->address,conn->port);
+
+ conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
+ return 0;
+}
+
/*
Local Variables:
mode:c
Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.340
retrieving revision 1.341
diff -u -d -r1.340 -r1.341
--- or.h 10 May 2004 17:30:51 -0000 1.340
+++ or.h 12 May 2004 19:17:09 -0000 1.341
@@ -1011,11 +1011,11 @@
tor_tls_get_pending_bytes((conn)->tls))
int connection_is_listener(connection_t *conn);
int connection_state_is_open(connection_t *conn);
+int connection_state_is_connecting(connection_t *conn);
int connection_send_destroy(uint16_t circ_id, connection_t *conn);
int connection_process_inbuf(connection_t *conn);
-int connection_finished_flushing(connection_t *conn);
void assert_connection_ok(connection_t *conn, time_t now);
@@ -1033,6 +1033,7 @@
connection_t *conn,
crypt_path_t *layer_hint);
int connection_edge_finished_flushing(connection_t *conn);
+int connection_edge_finished_connecting(connection_t *conn);
int connection_edge_package_raw_inbuf(connection_t *conn);
@@ -1062,6 +1063,7 @@
int connection_or_process_inbuf(connection_t *conn);
int connection_or_finished_flushing(connection_t *conn);
+int connection_or_finished_connecting(connection_t *conn);
connection_t *connection_or_connect(routerinfo_t *router);
@@ -1086,6 +1088,7 @@
const char *payload, int payload_len);
int connection_dir_process_inbuf(connection_t *conn);
int connection_dir_finished_flushing(connection_t *conn);
+int connection_dir_finished_connecting(connection_t *conn);
/********************************* dns.c ***************************/
More information about the tor-commits
mailing list