Loading src/or/circuit.c +30 −27 Original line number Diff line number Diff line Loading @@ -225,30 +225,6 @@ circuit_t *circuit_get_newest_ap(void) { return bestcirc; } int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, char edge_type, crypt_path_t *layer_hint) { int cell_direction; static int numsent_ap=0, numsent_exit=0; log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): called, edge_type %d.", edge_type); if(edge_type == EDGE_AP) { /* i'm the AP */ cell_direction = CELL_DIRECTION_OUT; numsent_ap++; log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): now sent %d relay cells from ap", numsent_ap); } else { /* i'm the exit */ cell_direction = CELL_DIRECTION_IN; numsent_exit++; log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): now sent %d relay cells from exit", numsent_exit); } if(circuit_deliver_relay_cell(cell, circ, cell_direction, layer_hint) < 0) { return -1; } return 0; } int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint) { connection_t *conn=NULL; Loading Loading @@ -483,7 +459,7 @@ int circuit_consider_sending_sendme(circuit_t *circ, int edge_type, crypt_path_t while(layer_hint->deliver_window < CIRCWINDOW_START-CIRCWINDOW_INCREMENT) { log(LOG_DEBUG,"circuit_consider_sending_sendme(): deliver_window %d, Queueing sendme forward.", layer_hint->deliver_window); layer_hint->deliver_window += CIRCWINDOW_INCREMENT; if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type, layer_hint) < 0) { if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, layer_hint) < 0) { return -1; } } Loading @@ -492,7 +468,7 @@ int circuit_consider_sending_sendme(circuit_t *circ, int edge_type, crypt_path_t while(circ->deliver_window < CIRCWINDOW_START-CIRCWINDOW_INCREMENT) { log(LOG_DEBUG,"circuit_consider_sending_sendme(): deliver_window %d, Queueing sendme back.", circ->deliver_window); circ->deliver_window += CIRCWINDOW_INCREMENT; if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type, layer_hint) < 0) { if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_IN, layer_hint) < 0) { return -1; } } Loading Loading @@ -801,7 +777,7 @@ int circuit_send_next_onion_skin(circuit_t *circ) { log(LOG_DEBUG,"circuit_send_next_onion_skin(): Sending extend relay cell."); /* send it to hop->prev, because it will transfer it to a create cell and then send to hop */ if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP, hop->prev) < 0) { if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, hop->prev) < 0) { log(LOG_DEBUG,"circuit_send_next_onion_skin(): failed to deliver extend cell. Closing."); return -1; } Loading Loading @@ -921,6 +897,33 @@ int circuit_finish_handshake(circuit_t *circ, char *reply) { return 0; } int circuit_truncated(circuit_t *circ, crypt_path_t *layer) { crypt_path_t *victim; connection_t *stream; assert(circ); assert(layer); while(layer->next != circ->cpath) { /* we need to clear out layer->next */ victim = layer->next; log(LOG_DEBUG, "circuit_truncated(): Killing a layer of the cpath."); for(stream = circ->p_streams; stream; stream=stream->next_stream) { if(stream->cpath_layer == victim) { log(LOG_DEBUG, "circuit_truncated(): Marking stream %d for close.", *(int*)stream->stream_id); stream->marked_for_close = 1; } } layer->next = victim->next; circuit_free_cpath_node(victim); } log(LOG_DEBUG, "circuit_truncated(): Complete."); return 0; } /* Local Variables: mode:c Loading src/or/command.c +1 −1 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ void command_process_created_cell(cell_t *cell, connection_t *conn) { memcpy(newcell.payload+RELAY_HEADER_SIZE, cell->payload, DH_KEY_LEN); log(LOG_DEBUG,"command_process_created_cell(): Sending extended relay cell."); if(circuit_deliver_relay_cell_from_edge(&newcell, circ, EDGE_EXIT, NULL) < 0) { if(circuit_deliver_relay_cell(&newcell, circ, CELL_DIRECTION_IN, NULL) < 0) { log(LOG_DEBUG,"command_process_created_cell(): failed to deliver extended cell. Closing."); circuit_close(circ); return; Loading src/or/connection.c +6 −6 Original line number Diff line number Diff line Loading @@ -685,8 +685,8 @@ repeat_connection_package_raw_inbuf: if(conn->type == CONN_TYPE_EXIT) { cell.aci = circ->p_aci; if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_EXIT, NULL) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell_from_edge (backward) failed. Closing."); if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_IN, NULL) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell (backward) failed. Closing."); circuit_close(circ); return 0; } Loading @@ -695,8 +695,8 @@ repeat_connection_package_raw_inbuf: } else { /* send it forward. we're an AP */ assert(conn->type == CONN_TYPE_AP); cell.aci = circ->n_aci; if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell_from_edge (forward) failed. Closing."); if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell (forward) failed. Closing."); circuit_close(circ); return 0; } Loading Loading @@ -749,8 +749,8 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) { while(conn->deliver_window < STREAMWINDOW_START - STREAMWINDOW_INCREMENT) { log(LOG_DEBUG,"connection_consider_sending_sendme(): Outbuf %d, Queueing stream sendme.", conn->outbuf_flushlen); conn->deliver_window += STREAMWINDOW_INCREMENT; if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_consider_sending_sendme(): circuit_deliver_relay_cell_from_edge failed. Closing."); if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION(edge_type), conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_consider_sending_sendme(): circuit_deliver_relay_cell failed. Closing."); circuit_close(circ); return 0; } Loading src/or/connection_ap.c +1 −1 Original line number Diff line number Diff line Loading @@ -136,7 +136,7 @@ int ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ) { "%s:%d", ap_conn->dest_addr, ap_conn->dest_port) + 1 + STREAM_ID_SIZE + RELAY_HEADER_SIZE; log(LOG_DEBUG,"ap_handshake_send_begin(): Sending relay cell (id %d) to begin stream %d.", *(int *)(cell.payload+1),*(int *)ap_conn->stream_id); if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP, ap_conn->cpath_layer) < 0) { if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, ap_conn->cpath_layer) < 0) { log(LOG_DEBUG,"ap_handshake_send_begin(): failed to deliver begin cell. Closing."); return -1; } Loading src/or/connection_edge.c +36 −12 Original line number Diff line number Diff line Loading @@ -31,8 +31,8 @@ int connection_edge_process_inbuf(connection_t *conn) { SET_CELL_STREAM_ID(cell, conn->stream_id); cell.aci = circ->n_aci; if (circuit_deliver_relay_cell_from_edge(&cell, circ, conn->type, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_edge_process_inbuf: circuit_deliver_relay_cell_from_edge failed. Closing"); if (circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION(conn->type), conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_edge_process_inbuf: circuit_deliver_relay_cell failed. Closing."); circuit_close(circ); } return 0; Loading Loading @@ -60,30 +60,37 @@ int connection_edge_process_inbuf(connection_t *conn) { return 0; } int connection_edge_send_command(connection_t *conn, circuit_t *circ, int relay_command) { int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int relay_command) { cell_t cell; assert(conn); int cell_direction; if(!circ) { log(LOG_DEBUG,"connection_edge_send_command(): conn has no circ. Closing."); log(LOG_DEBUG,"connection_edge_send_command(): no circ. Closing."); return -1; } memset(&cell, 0, sizeof(cell_t)); if(conn->type == CONN_TYPE_AP) if(fromconn && fromconn->type == CONN_TYPE_AP) { cell.aci = circ->n_aci; else cell_direction = CELL_DIRECTION_OUT; } else { /* NOTE: if !fromconn, we assume that it's heading towards the OP */ cell.aci = circ->p_aci; cell_direction = CELL_DIRECTION_IN; } cell.command = CELL_RELAY; SET_CELL_RELAY_COMMAND(cell, relay_command); SET_CELL_STREAM_ID(cell, conn->stream_id); if(fromconn) SET_CELL_STREAM_ID(cell, fromconn->stream_id); else SET_CELL_STREAM_ID(cell, ZERO_STREAM); cell.length = RELAY_HEADER_SIZE; log(LOG_INFO,"connection_edge_send_command(): delivering %d cell %s.", relay_command, conn->type == CONN_TYPE_AP ? "forward" : "backward"); log(LOG_INFO,"connection_edge_send_command(): delivering %d cell %s.", relay_command, cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward"); if(circuit_deliver_relay_cell_from_edge(&cell, circ, conn->type, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_edge_send_command(): circuit_deliver_relay_cell_from_edge failed. Closing."); if(circuit_deliver_relay_cell(&cell, circ, cell_direction, fromconn ? fromconn->cpath_layer : NULL) < 0) { log(LOG_DEBUG,"connection_edge_send_command(): circuit_deliver_relay_cell failed. Closing."); circuit_close(circ); return 0; } Loading Loading @@ -199,6 +206,23 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection return -1; } return circuit_send_next_onion_skin(circ); case RELAY_COMMAND_TRUNCATE: if(edge_type == EDGE_AP) { log(LOG_INFO,"connection_edge_process_relay_cell(): 'truncate' unsupported at AP. Dropping."); return 0; } if(circ->n_conn) { connection_send_destroy(circ->n_aci, circ->n_conn); circ->n_conn = NULL; } log(LOG_DEBUG, "connection_edge_process_relay_cell(): Processed 'truncate', replying."); return connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED); case RELAY_COMMAND_TRUNCATED: if(edge_type == EDGE_EXIT) { log(LOG_INFO,"connection_edge_process_relay_cell(): 'truncated' unsupported at exit. Dropping."); return 0; } return circuit_truncated(circ, layer_hint); case RELAY_COMMAND_CONNECTED: if(edge_type == EDGE_EXIT) { log(LOG_INFO,"connection_edge_process_relay_cell(): 'connected' unsupported at exit. Dropping."); Loading Loading
src/or/circuit.c +30 −27 Original line number Diff line number Diff line Loading @@ -225,30 +225,6 @@ circuit_t *circuit_get_newest_ap(void) { return bestcirc; } int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, char edge_type, crypt_path_t *layer_hint) { int cell_direction; static int numsent_ap=0, numsent_exit=0; log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): called, edge_type %d.", edge_type); if(edge_type == EDGE_AP) { /* i'm the AP */ cell_direction = CELL_DIRECTION_OUT; numsent_ap++; log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): now sent %d relay cells from ap", numsent_ap); } else { /* i'm the exit */ cell_direction = CELL_DIRECTION_IN; numsent_exit++; log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): now sent %d relay cells from exit", numsent_exit); } if(circuit_deliver_relay_cell(cell, circ, cell_direction, layer_hint) < 0) { return -1; } return 0; } int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint) { connection_t *conn=NULL; Loading Loading @@ -483,7 +459,7 @@ int circuit_consider_sending_sendme(circuit_t *circ, int edge_type, crypt_path_t while(layer_hint->deliver_window < CIRCWINDOW_START-CIRCWINDOW_INCREMENT) { log(LOG_DEBUG,"circuit_consider_sending_sendme(): deliver_window %d, Queueing sendme forward.", layer_hint->deliver_window); layer_hint->deliver_window += CIRCWINDOW_INCREMENT; if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type, layer_hint) < 0) { if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, layer_hint) < 0) { return -1; } } Loading @@ -492,7 +468,7 @@ int circuit_consider_sending_sendme(circuit_t *circ, int edge_type, crypt_path_t while(circ->deliver_window < CIRCWINDOW_START-CIRCWINDOW_INCREMENT) { log(LOG_DEBUG,"circuit_consider_sending_sendme(): deliver_window %d, Queueing sendme back.", circ->deliver_window); circ->deliver_window += CIRCWINDOW_INCREMENT; if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type, layer_hint) < 0) { if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_IN, layer_hint) < 0) { return -1; } } Loading Loading @@ -801,7 +777,7 @@ int circuit_send_next_onion_skin(circuit_t *circ) { log(LOG_DEBUG,"circuit_send_next_onion_skin(): Sending extend relay cell."); /* send it to hop->prev, because it will transfer it to a create cell and then send to hop */ if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP, hop->prev) < 0) { if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, hop->prev) < 0) { log(LOG_DEBUG,"circuit_send_next_onion_skin(): failed to deliver extend cell. Closing."); return -1; } Loading Loading @@ -921,6 +897,33 @@ int circuit_finish_handshake(circuit_t *circ, char *reply) { return 0; } int circuit_truncated(circuit_t *circ, crypt_path_t *layer) { crypt_path_t *victim; connection_t *stream; assert(circ); assert(layer); while(layer->next != circ->cpath) { /* we need to clear out layer->next */ victim = layer->next; log(LOG_DEBUG, "circuit_truncated(): Killing a layer of the cpath."); for(stream = circ->p_streams; stream; stream=stream->next_stream) { if(stream->cpath_layer == victim) { log(LOG_DEBUG, "circuit_truncated(): Marking stream %d for close.", *(int*)stream->stream_id); stream->marked_for_close = 1; } } layer->next = victim->next; circuit_free_cpath_node(victim); } log(LOG_DEBUG, "circuit_truncated(): Complete."); return 0; } /* Local Variables: mode:c Loading
src/or/command.c +1 −1 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ void command_process_created_cell(cell_t *cell, connection_t *conn) { memcpy(newcell.payload+RELAY_HEADER_SIZE, cell->payload, DH_KEY_LEN); log(LOG_DEBUG,"command_process_created_cell(): Sending extended relay cell."); if(circuit_deliver_relay_cell_from_edge(&newcell, circ, EDGE_EXIT, NULL) < 0) { if(circuit_deliver_relay_cell(&newcell, circ, CELL_DIRECTION_IN, NULL) < 0) { log(LOG_DEBUG,"command_process_created_cell(): failed to deliver extended cell. Closing."); circuit_close(circ); return; Loading
src/or/connection.c +6 −6 Original line number Diff line number Diff line Loading @@ -685,8 +685,8 @@ repeat_connection_package_raw_inbuf: if(conn->type == CONN_TYPE_EXIT) { cell.aci = circ->p_aci; if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_EXIT, NULL) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell_from_edge (backward) failed. Closing."); if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_IN, NULL) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell (backward) failed. Closing."); circuit_close(circ); return 0; } Loading @@ -695,8 +695,8 @@ repeat_connection_package_raw_inbuf: } else { /* send it forward. we're an AP */ assert(conn->type == CONN_TYPE_AP); cell.aci = circ->n_aci; if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell_from_edge (forward) failed. Closing."); if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell (forward) failed. Closing."); circuit_close(circ); return 0; } Loading Loading @@ -749,8 +749,8 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) { while(conn->deliver_window < STREAMWINDOW_START - STREAMWINDOW_INCREMENT) { log(LOG_DEBUG,"connection_consider_sending_sendme(): Outbuf %d, Queueing stream sendme.", conn->outbuf_flushlen); conn->deliver_window += STREAMWINDOW_INCREMENT; if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_consider_sending_sendme(): circuit_deliver_relay_cell_from_edge failed. Closing."); if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION(edge_type), conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_consider_sending_sendme(): circuit_deliver_relay_cell failed. Closing."); circuit_close(circ); return 0; } Loading
src/or/connection_ap.c +1 −1 Original line number Diff line number Diff line Loading @@ -136,7 +136,7 @@ int ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ) { "%s:%d", ap_conn->dest_addr, ap_conn->dest_port) + 1 + STREAM_ID_SIZE + RELAY_HEADER_SIZE; log(LOG_DEBUG,"ap_handshake_send_begin(): Sending relay cell (id %d) to begin stream %d.", *(int *)(cell.payload+1),*(int *)ap_conn->stream_id); if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP, ap_conn->cpath_layer) < 0) { if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, ap_conn->cpath_layer) < 0) { log(LOG_DEBUG,"ap_handshake_send_begin(): failed to deliver begin cell. Closing."); return -1; } Loading
src/or/connection_edge.c +36 −12 Original line number Diff line number Diff line Loading @@ -31,8 +31,8 @@ int connection_edge_process_inbuf(connection_t *conn) { SET_CELL_STREAM_ID(cell, conn->stream_id); cell.aci = circ->n_aci; if (circuit_deliver_relay_cell_from_edge(&cell, circ, conn->type, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_edge_process_inbuf: circuit_deliver_relay_cell_from_edge failed. Closing"); if (circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION(conn->type), conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_edge_process_inbuf: circuit_deliver_relay_cell failed. Closing."); circuit_close(circ); } return 0; Loading Loading @@ -60,30 +60,37 @@ int connection_edge_process_inbuf(connection_t *conn) { return 0; } int connection_edge_send_command(connection_t *conn, circuit_t *circ, int relay_command) { int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int relay_command) { cell_t cell; assert(conn); int cell_direction; if(!circ) { log(LOG_DEBUG,"connection_edge_send_command(): conn has no circ. Closing."); log(LOG_DEBUG,"connection_edge_send_command(): no circ. Closing."); return -1; } memset(&cell, 0, sizeof(cell_t)); if(conn->type == CONN_TYPE_AP) if(fromconn && fromconn->type == CONN_TYPE_AP) { cell.aci = circ->n_aci; else cell_direction = CELL_DIRECTION_OUT; } else { /* NOTE: if !fromconn, we assume that it's heading towards the OP */ cell.aci = circ->p_aci; cell_direction = CELL_DIRECTION_IN; } cell.command = CELL_RELAY; SET_CELL_RELAY_COMMAND(cell, relay_command); SET_CELL_STREAM_ID(cell, conn->stream_id); if(fromconn) SET_CELL_STREAM_ID(cell, fromconn->stream_id); else SET_CELL_STREAM_ID(cell, ZERO_STREAM); cell.length = RELAY_HEADER_SIZE; log(LOG_INFO,"connection_edge_send_command(): delivering %d cell %s.", relay_command, conn->type == CONN_TYPE_AP ? "forward" : "backward"); log(LOG_INFO,"connection_edge_send_command(): delivering %d cell %s.", relay_command, cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward"); if(circuit_deliver_relay_cell_from_edge(&cell, circ, conn->type, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_edge_send_command(): circuit_deliver_relay_cell_from_edge failed. Closing."); if(circuit_deliver_relay_cell(&cell, circ, cell_direction, fromconn ? fromconn->cpath_layer : NULL) < 0) { log(LOG_DEBUG,"connection_edge_send_command(): circuit_deliver_relay_cell failed. Closing."); circuit_close(circ); return 0; } Loading Loading @@ -199,6 +206,23 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection return -1; } return circuit_send_next_onion_skin(circ); case RELAY_COMMAND_TRUNCATE: if(edge_type == EDGE_AP) { log(LOG_INFO,"connection_edge_process_relay_cell(): 'truncate' unsupported at AP. Dropping."); return 0; } if(circ->n_conn) { connection_send_destroy(circ->n_aci, circ->n_conn); circ->n_conn = NULL; } log(LOG_DEBUG, "connection_edge_process_relay_cell(): Processed 'truncate', replying."); return connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED); case RELAY_COMMAND_TRUNCATED: if(edge_type == EDGE_EXIT) { log(LOG_INFO,"connection_edge_process_relay_cell(): 'truncated' unsupported at exit. Dropping."); return 0; } return circuit_truncated(circ, layer_hint); case RELAY_COMMAND_CONNECTED: if(edge_type == EDGE_EXIT) { log(LOG_INFO,"connection_edge_process_relay_cell(): 'connected' unsupported at exit. Dropping."); Loading