mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
let introcircs receive acks. rend streams now deal correctly again.
(i think) svn:r1614
This commit is contained in:
parent
5514ad715b
commit
1d7979b460
@ -275,9 +275,10 @@ static int circuit_is_acceptable(circuit_t *circ,
|
||||
if(purpose == CIRCUIT_PURPOSE_C_REND_JOINED && !must_be_open) {
|
||||
if(circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
|
||||
circ->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
|
||||
circ->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED &&
|
||||
circ->purpose != CIRCUIT_PURPOSE_C_REND_JOINED)
|
||||
return 0;
|
||||
} else if (purpose == CIRCUIT_PURPOSE_C_INTRODUCING) {
|
||||
} else if (purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT && !must_be_open) {
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCING &&
|
||||
circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
|
||||
return 0;
|
||||
@ -311,8 +312,10 @@ static int circuit_is_acceptable(circuit_t *circ,
|
||||
return 0;
|
||||
}
|
||||
} else { /* not general */
|
||||
if(rend_cmp_service_ids(conn->rend_query, circ->rend_query)) {
|
||||
/* this circ is not for this conn */
|
||||
if(rend_cmp_service_ids(conn->rend_query, circ->rend_query) &&
|
||||
(circ->rend_query[0] || purpose != CIRCUIT_PURPOSE_C_REND_JOINED)) {
|
||||
/* this circ is not for this conn, and it's not suitable
|
||||
* for cannibalizing either */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -340,9 +343,9 @@ static int circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case CIRCUIT_PURPOSE_C_INTRODUCING:
|
||||
/* more recently created is best */
|
||||
if(a->timestamp_created > b->timestamp_created)
|
||||
case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
|
||||
/* the closer it is to ack_wait the better it is */
|
||||
if(a->purpose > b->purpose)
|
||||
return 1;
|
||||
break;
|
||||
case CIRCUIT_PURPOSE_C_REND_JOINED:
|
||||
@ -356,25 +359,28 @@ static int circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
|
||||
|
||||
/* Find the best circ that conn can use, preferably one which is
|
||||
* dirty. Circ must not be too old.
|
||||
* If !conn, return newest.
|
||||
* conn must be defined.
|
||||
*
|
||||
* If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN.
|
||||
*
|
||||
* circ_purpose specifies what sort of circuit we must have.
|
||||
* It can be C_GENERAL, C_INTRODUCING, or C_REND_JOINED.
|
||||
* It can be C_GENERAL, C_INTRODUCE_ACK_WAIT, or C_REND_JOINED.
|
||||
*
|
||||
* If it's REND_JOINED and must_be_open==0, then return the closest
|
||||
* rendezvous-purposed circuit that you can find.
|
||||
*
|
||||
* If circ_purpose is not GENERAL, then conn must be defined.
|
||||
* If it's INTRODUCE_ACK_WAIT and must_be_open==0, then return the
|
||||
* closest introduce-purposed circuit that you can find.
|
||||
*/
|
||||
circuit_t *circuit_get_best(connection_t *conn,
|
||||
int must_be_open, uint8_t purpose) {
|
||||
circuit_t *circ, *best=NULL;
|
||||
time_t now = time(NULL);
|
||||
|
||||
assert(conn);
|
||||
|
||||
assert(purpose == CIRCUIT_PURPOSE_C_GENERAL ||
|
||||
purpose == CIRCUIT_PURPOSE_C_INTRODUCING ||
|
||||
purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT ||
|
||||
purpose == CIRCUIT_PURPOSE_C_REND_JOINED);
|
||||
|
||||
for (circ=global_circuitlist;circ;circ = circ->next) {
|
||||
@ -391,6 +397,18 @@ circuit_t *circuit_get_best(connection_t *conn,
|
||||
return best;
|
||||
}
|
||||
|
||||
circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose) {
|
||||
circuit_t *circ;
|
||||
|
||||
for (circ = global_circuitlist; circ; circ = circ->next) {
|
||||
if (!circ->marked_for_close &&
|
||||
circ->purpose == purpose &&
|
||||
!rend_cmp_service_ids(rend_query, circ->rend_query))
|
||||
return circ;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the first circuit in global_circuitlist after 'start' whose
|
||||
* rend_pk_digest field is 'digest' and whose purpose is purpose. Returns
|
||||
* NULL if no circuit is found. If 'start' is null, begin at the start of
|
||||
|
@ -806,7 +806,7 @@ circuit_get_open_circ_or_launch(connection_t *conn,
|
||||
char *exitname=NULL;
|
||||
uint8_t new_circ_purpose;
|
||||
|
||||
if(desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCING) {
|
||||
if(desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
|
||||
/* need to pick an intro point */
|
||||
exitname = rend_client_get_random_intro(conn->rend_query);
|
||||
if(!exitname) {
|
||||
@ -823,6 +823,8 @@ circuit_get_open_circ_or_launch(connection_t *conn,
|
||||
|
||||
if(desired_circuit_purpose == CIRCUIT_PURPOSE_C_REND_JOINED)
|
||||
new_circ_purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
|
||||
else if(desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
|
||||
new_circ_purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
|
||||
else
|
||||
new_circ_purpose = desired_circuit_purpose;
|
||||
|
||||
@ -893,16 +895,13 @@ int connection_ap_handshake_attach_circuit(connection_t *conn) {
|
||||
} else { /* we're a rendezvous conn */
|
||||
circuit_t *rendcirc=NULL, *introcirc=NULL;
|
||||
|
||||
/* before anything else, see if we've already been attached
|
||||
* to a rendezvous circuit */
|
||||
if(conn->cpath_layer) {
|
||||
return 1;
|
||||
}
|
||||
assert(!conn->cpath_layer);
|
||||
|
||||
/* else, start by finding a rendezvous circuit for us */
|
||||
/* start by finding a rendezvous circuit for us */
|
||||
|
||||
retval = circuit_get_open_circ_or_launch(conn, CIRCUIT_PURPOSE_C_REND_JOINED, &rendcirc);
|
||||
if(retval < 0) return -1; /* failed */
|
||||
assert(rendcirc);
|
||||
|
||||
if(retval > 0) {
|
||||
/* one is already established, attach */
|
||||
@ -913,36 +912,41 @@ int connection_ap_handshake_attach_circuit(connection_t *conn) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(rendcirc &&
|
||||
rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY &&
|
||||
rendcirc->build_state->pending_final_cpath) {
|
||||
log_fn(LOG_INFO,"pending-join circ already here. reusing.");
|
||||
link_apconn_to_circ(conn, rendcirc);
|
||||
/* don't send the begin, because we're still waiting for contact from bob */
|
||||
return 1;
|
||||
if(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) {
|
||||
log_fn(LOG_INFO,"pending-join circ already here, with intro ack. Stalling.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* it's on its way. find an intro circ. */
|
||||
retval = circuit_get_open_circ_or_launch(conn, CIRCUIT_PURPOSE_C_INTRODUCING, &introcirc);
|
||||
retval = circuit_get_open_circ_or_launch(conn, CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT, &introcirc);
|
||||
if(retval < 0) return -1; /* failed */
|
||||
assert(introcirc);
|
||||
|
||||
if(retval > 0) {
|
||||
log_fn(LOG_INFO,"Intro circ is ready for us");
|
||||
if(rendcirc &&
|
||||
rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
|
||||
/* then we know !pending_final_cpath, from above */
|
||||
log_fn(LOG_INFO,"intro and rend circs are both ready. introducing.");
|
||||
/* this call marks introcirc for close */
|
||||
/* one has already sent the intro. keep waiting. */
|
||||
log_fn(LOG_INFO,"Intro circ present and awaiting ack. Stalling.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* now both rendcirc and introcirc are defined, and neither is finished */
|
||||
|
||||
if(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
|
||||
log_fn(LOG_INFO,"ready rend circ already here (no intro-ack yet).");
|
||||
/* look around for any new intro circs that should introduce */
|
||||
|
||||
assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
if(introcirc->state == CIRCUIT_STATE_OPEN) {
|
||||
log_fn(LOG_INFO,"found open intro circ; sending introduction.");
|
||||
/* XXX here we should cannibalize the rend circ if it's a zero service id */
|
||||
if(rend_client_send_introduction(introcirc, rendcirc) < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* now attach conn to rendcirc */
|
||||
link_apconn_to_circ(conn, rendcirc);
|
||||
if(!rendcirc->timestamp_dirty)
|
||||
rendcirc->timestamp_dirty = time(NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
log_fn(LOG_INFO,"Intro and rend circs are not both ready. Stalling conn.");
|
||||
return 0;
|
||||
}
|
||||
|
22
src/or/or.h
22
src/or/or.h
@ -209,10 +209,12 @@
|
||||
* circuits that are c_establish_rend are either on their way
|
||||
* to becoming open, or they are open and have sent the
|
||||
* establish_rendezvous cell but haven't received an ack.
|
||||
* circuits that are c_rend_ready are open and have received an
|
||||
* ack, but haven't heard from bob yet. if they have a
|
||||
* circuits that are c_rend_ready are open and have received a
|
||||
* rend ack, but haven't heard from bob yet. if they have a
|
||||
* buildstate->pending_final_cpath then they're expecting a
|
||||
* cell from bob, else they're not.
|
||||
* circuits that are c_rend_ready_intro_acked are open, and
|
||||
* some intro circ has sent its intro and received an ack.
|
||||
* circuits that are c_rend_joined are open, have heard from
|
||||
* bob, and are talking to him.
|
||||
*/
|
||||
@ -222,14 +224,15 @@
|
||||
|
||||
#define CIRCUIT_PURPOSE_C_ESTABLISH_REND 8 /* at Alice, waiting for ack */
|
||||
#define CIRCUIT_PURPOSE_C_REND_READY 9 /* at Alice, waiting for Bob */
|
||||
#define CIRCUIT_PURPOSE_C_REND_JOINED 10 /* at Alice, rendezvous established */
|
||||
#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED 10 /* at Alice, waiting for Bob */
|
||||
#define CIRCUIT_PURPOSE_C_REND_JOINED 11 /* at Alice, rendezvous established */
|
||||
|
||||
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 11 /* at Bob, waiting for introductions */
|
||||
#define CIRCUIT_PURPOSE_S_INTRO 12 /* at Bob, successfully established intro */
|
||||
#define CIRCUIT_PURPOSE_S_CONNECT_REND 13 /* at Bob, connecting to rend point */
|
||||
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 12 /* at Bob, waiting for introductions */
|
||||
#define CIRCUIT_PURPOSE_S_INTRO 13 /* at Bob, successfully established intro */
|
||||
#define CIRCUIT_PURPOSE_S_CONNECT_REND 14 /* at Bob, connecting to rend point */
|
||||
|
||||
#define CIRCUIT_PURPOSE_S_REND_JOINED 14 /* at Bob, rendezvous established.*/
|
||||
#define _CIRCUIT_PURPOSE_MAX 14
|
||||
#define CIRCUIT_PURPOSE_S_REND_JOINED 15 /* at Bob, rendezvous established.*/
|
||||
#define _CIRCUIT_PURPOSE_MAX 15
|
||||
|
||||
#define CIRCUIT_PURPOSE_IS_ORIGIN(p) ((p)>_CIRCUIT_PURPOSE_OR_MAX)
|
||||
#define CIRCUIT_IS_ORIGIN(c) (CIRCUIT_PURPOSE_IS_ORIGIN((c)->purpose))
|
||||
@ -685,6 +688,7 @@ circuit_t *circuit_get_by_circ_id_conn(uint16_t circ_id, connection_t *conn);
|
||||
circuit_t *circuit_get_by_conn(connection_t *conn);
|
||||
circuit_t *circuit_get_best(connection_t *conn,
|
||||
int must_be_open, uint8_t purpose);
|
||||
circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose);
|
||||
circuit_t *circuit_get_next_by_pk_and_purpose(circuit_t *circuit,
|
||||
const char *servid, uint8_t purpose);
|
||||
circuit_t *circuit_get_rendezvous(const char *cookie);
|
||||
@ -1038,7 +1042,7 @@ int rend_client_rendezvous_acked(circuit_t *circ, const char *request, int reque
|
||||
int rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request_len);
|
||||
void rend_client_desc_fetched(char *query, int success);
|
||||
|
||||
int rend_cmp_service_ids(char *one, char *two);
|
||||
int rend_cmp_service_ids(const char *one, const char *two);
|
||||
char *rend_client_get_random_intro(char *query);
|
||||
int rend_parse_rendezvous_address(char *address);
|
||||
|
||||
|
@ -8,16 +8,11 @@
|
||||
void
|
||||
rend_client_introcirc_is_open(circuit_t *circ)
|
||||
{
|
||||
circuit_t *rendcirc = NULL;
|
||||
assert(circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
assert(CIRCUIT_IS_ORIGIN(circ) && circ->cpath);
|
||||
|
||||
log_fn(LOG_INFO,"introcirc is open");
|
||||
connection_ap_attach_pending();
|
||||
while ((rendcirc = circuit_get_next_by_pk_and_purpose(
|
||||
rendcirc, circ->rend_pk_digest, CIRCUIT_PURPOSE_C_REND_READY))) {
|
||||
rend_client_send_introduction(circ, rendcirc);
|
||||
}
|
||||
}
|
||||
|
||||
/* send the establish-rendezvous cell. if it fails, mark
|
||||
@ -154,6 +149,7 @@ rend_client_introduction_acked(circuit_t *circ,
|
||||
int i, r;
|
||||
rend_cache_entry_t *ent;
|
||||
char *nickname;
|
||||
circuit_t *rendcirc;
|
||||
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
|
||||
log_fn(LOG_WARN, "Received REND_INTRODUCE_ACK on unexpected circuit %d",
|
||||
@ -166,7 +162,15 @@ rend_client_introduction_acked(circuit_t *circ,
|
||||
|
||||
if (request_len == 0) {
|
||||
/* It's an ACK; the introduction point relayed our introduction request. */
|
||||
/* So close the circuit; we won't need it any more. */
|
||||
/* Locate the rend circ which is waiting to hear about this ack,
|
||||
* and tell it.
|
||||
*/
|
||||
rendcirc = circuit_get_by_rend_query_and_purpose(
|
||||
circ->rend_query, CIRCUIT_PURPOSE_C_REND_READY);
|
||||
if(rendcirc) { /* remember the ack */
|
||||
rendcirc->purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
|
||||
}
|
||||
/* close the circuit: we won't need it anymore. */
|
||||
circuit_mark_for_close(circ);
|
||||
} else {
|
||||
/* It's a NAK; the introduction point didn't relay our request. */
|
||||
@ -305,13 +309,6 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request
|
||||
|
||||
onion_append_to_cpath(&circ->cpath, hop);
|
||||
circ->build_state->pending_final_cpath = NULL; /* prevent double-free */
|
||||
|
||||
for(apconn = circ->p_streams; apconn; apconn = apconn->next_stream) {
|
||||
apconn->cpath_layer = circ->cpath->prev;
|
||||
/* now the last hop is different. be sure to send all the way. */
|
||||
if(connection_ap_handshake_send_begin(apconn, circ) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
circuit_mark_for_close(circ);
|
||||
@ -356,7 +353,7 @@ void rend_client_desc_fetched(char *query, int success) {
|
||||
}
|
||||
}
|
||||
|
||||
int rend_cmp_service_ids(char *one, char *two) {
|
||||
int rend_cmp_service_ids(const char *one, const char *two) {
|
||||
return strcasecmp(one,two);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user