summaryrefslogtreecommitdiff
path: root/src/or/connection_edge.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-03-17 12:38:37 +0000
committerNick Mathewson <nickm@torproject.org>2005-03-17 12:38:37 +0000
commitdf9c8feac782c9feebad3a0fc7cc5eb7068bccf2 (patch)
treead090affe0b93f33441afeddda27990a33f32464 /src/or/connection_edge.c
parentb5a7347db50ad76e8e1aaf6a6a88f733c202ca37 (diff)
downloadtor-df9c8feac782c9feebad3a0fc7cc5eb7068bccf2.tar.gz
tor-df9c8feac782c9feebad3a0fc7cc5eb7068bccf2.zip
Commit fixes for several pending tor core tasks: document all DOCDOCed functions; time out uncontrolled unattached streams; feed reasons to SOCKS5 (refactoring connection_ap_handshake_socks_reply in the process); change DirFetchPeriod/StatusFetchPeriod to have a special "Be smart" value.
svn:r3769
Diffstat (limited to 'src/or/connection_edge.c')
-rw-r--r--src/or/connection_edge.c96
1 files changed, 65 insertions, 31 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index fe77f43669..f3efb0498b 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -162,7 +162,10 @@ connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_layer)
return 0;
}
-/** DOCDOC **/
+/** An error has just occured on an operation on an edge connection
+ * <b>conn</b>. Extract the errno; convert it to an end reason, and send
+ * an appropriate relay end cell to <b>cpath_layer</b>.
+ **/
int
connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer)
{
@@ -265,7 +268,15 @@ void connection_ap_expire_beginning(void) {
conn = carray[i];
if (conn->type != CONN_TYPE_AP)
continue;
- if (conn->state != AP_CONN_STATE_RESOLVE_WAIT &&
+ if (conn->state == AP_CONN_STATE_CONTROLLER_WAIT) {
+ if (now - conn->timestamp_lastread >= 120) {
+ log_fn(LOG_NOTICE, "Closing unattached stream.");
+ connection_mark_for_close(conn);
+ }
+ continue;
+ }
+
+ else if (conn->state != AP_CONN_STATE_RESOLVE_WAIT &&
conn->state != AP_CONN_STATE_CONNECT_WAIT)
continue;
if (now - conn->timestamp_lastread < 15)
@@ -338,17 +349,21 @@ void connection_ap_attach_pending(void)
}
}
-/** DOCDOC
- * -1 on err, 1 on success, 0 on not-yet-sure.
+/** The AP connection <b>conn</b> has just failed while attaching or
+ * sending a BEGIN or resolving on <b>circ</b>, but another circuit
+ * might work. Detach the circuit, and either reattach it, launch a
+ * new circuit, tell the controller, or give up as a appropriate.
+ *
+ * Returns -1 on err, 1 on success, 0 on not-yet-sure.
*/
int
connection_ap_detach_retriable(connection_t *conn, circuit_t *circ)
{
control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE);
+ conn->timestamp_lastread = time(NULL);
if (get_options()->ManageConnections) {
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
circuit_detach_stream(circ,conn);
- /* Muck with timestamps? */
return connection_ap_handshake_attach_circuit(conn);
} else {
conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
@@ -678,7 +693,15 @@ addressmap_get_virtual_address(int type)
}
}
-/* DOCDOC */
+/** A controller has requested that we map some address of type
+ * <b>type</b> to the address <b>new_address</b>. Choose an address
+ * that is unlikely to be used, and map it, and return it in a newly
+ * allocated string. If another address of the same type is already
+ * mapped to <b>new_address</b>, try to return a copy of that address.
+ *
+ * The string in <b>new_address</b> may be freed, or inserted into a map
+ * as appropriate.
+ **/
char *
addressmap_register_virtual_address(int type, char *new_address)
{
@@ -720,7 +743,7 @@ address_is_invalid_destination(const char *address) {
return 0;
}
-/* Iterate over all address mapings which have exipry times between
+/** Iterate over all address mapings which have exipry times between
* min_expires and max_expires, inclusive. If sl is provided, add an
* "old-addr new-addr" string to sl for each mapping. If sl is NULL,
* remove the mappings.
@@ -779,19 +802,23 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
log_fn(LOG_DEBUG,"entered.");
sockshere = fetch_from_buf_socks(conn->inbuf, socks);
- if (sockshere == -1 || sockshere == 0) {
+ if (sockshere == 0) {
+ if (socks->replylen) {
+ connection_write_to_buf(socks->reply, socks->replylen, conn);
+ } else {
+ log_fn(LOG_DEBUG,"socks handshake not all here yet.");
+ }
+ return 0;
+ } else if (sockshere == -1) {
if (socks->replylen) { /* we should send reply back */
log_fn(LOG_DEBUG,"reply is already set for us. Using it.");
- connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen, 0);
+ connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen,
+ SOCKS5_GENERAL_ERROR);
socks->replylen = 0; /* zero it out so we can do another round of negotiation */
- } else if (sockshere == -1) { /* send normal reject */
- log_fn(LOG_WARN,"Fetching socks handshake failed. Closing.");
- connection_ap_handshake_socks_reply(conn, NULL, 0, -1);
} else {
- log_fn(LOG_DEBUG,"socks handshake not all here yet.");
+ log_fn(LOG_WARN,"Fetching socks handshake failed. Closing.");
+ connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_GENERAL_ERROR);
}
- if (sockshere == -1)
- socks->has_finished = 1;
return sockshere;
} /* else socks handshake is done, continue processing */
@@ -1080,7 +1107,11 @@ int connection_ap_make_bridge(char *address, uint16_t port) {
return fd[1];
}
-/* DOCDOC */
+/** Send an answer to an AP connection that has requested a DNS lookup
+ * via SOCKS. The type should be one of RESOLVED_TYPE_(IPV4|IPV6) or
+ * -1 for unreachable; the answer should be in the format specified
+ * in the socks extensions document.
+ **/
void connection_ap_handshake_socks_resolved(connection_t *conn,
int answer_type,
size_t answer_len,
@@ -1132,15 +1163,15 @@ void connection_ap_handshake_socks_resolved(connection_t *conn,
}
}
connection_ap_handshake_socks_reply(conn, buf, replylen,
- (answer_type == RESOLVED_TYPE_IPV4 ||
- answer_type == RESOLVED_TYPE_IPV6) ? 1 : -1);
+ (answer_type == RESOLVED_TYPE_IPV4 ||
+ answer_type == RESOLVED_TYPE_IPV6) ?
+ SOCKS5_SUCCEEDED : SOCKS5_HOST_UNREACHABLE);
conn->socks_request->has_finished = 1;
}
/** Send a socks reply to stream <b>conn</b>, using the appropriate
- * socks version, etc.
- *
- * Status can be 1 (succeeded), -1 (failed), or 0 (not sure yet).
+ * socks version, etc, and mark <b>conn</b> as completed with SOCKS
+ * handshaking.
*
* If <b>reply</b> is defined, then write <b>replylen</b> bytes of it
* to conn and return, else reply based on <b>status</b>.
@@ -1148,32 +1179,34 @@ void connection_ap_handshake_socks_resolved(connection_t *conn,
* If <b>reply</b> is undefined, <b>status</b> can't be 0.
*/
void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
- size_t replylen, int status) {
+ size_t replylen,
+ socks5_reply_status_t status) {
char buf[256];
- if (status) /* it's either 1 or -1 */
- control_event_stream_status(conn,
- status==1 ? STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED);
+ control_event_stream_status(conn,
+ status==SOCKS5_SUCCEEDED ? STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED);
+ tor_assert(conn->socks_request);
+ if (conn->socks_request->has_finished) {
+ log_fn(LOG_WARN, "Harmless bug: duplicate calls to connection_ap_handshake_socks_reply.");
+ return;
+ }
if (replylen) { /* we already have a reply in mind */
connection_write_to_buf(reply, replylen, conn);
+ conn->socks_request->has_finished = 1;
return;
}
- tor_assert(conn->socks_request);
- tor_assert(status == 1 || status == -1);
if (conn->socks_request->socks_version == 4) {
memset(buf,0,SOCKS4_NETWORK_LEN);
#define SOCKS4_GRANTED 90
#define SOCKS4_REJECT 91
- buf[1] = (status==1 ? SOCKS4_GRANTED : SOCKS4_REJECT);
+ buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT);
/* leave version, destport, destip zero */
connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, conn);
}
if (conn->socks_request->socks_version == 5) {
buf[0] = 5; /* version 5 */
-#define SOCKS5_SUCCESS 0
-#define SOCKS5_GENERIC_ERROR 1
- buf[1] = status==1 ? SOCKS5_SUCCESS : SOCKS5_GENERIC_ERROR;
+ buf[1] = (char)status;
buf[2] = 0;
buf[3] = 1; /* ipv4 addr */
memset(buf+4,0,6); /* Set external addr/port to 0.
@@ -1182,6 +1215,7 @@ void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
}
/* If socks_version isn't 4 or 5, don't send anything.
* This can happen in the case of AP bridges. */
+ conn->socks_request->has_finished = 1;
return;
}