|
@@ -1031,6 +1031,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
|
|
relay_header_t rh;
|
|
|
unsigned domain = layer_hint?LD_APP:LD_EXIT;
|
|
|
int reason;
|
|
|
+ int optimistic_data = 0; /* Set to 1 if we receive data on a stream
|
|
|
+ * that's in the EXIT_CONN_STATE_RESOLVING
|
|
|
+ * or EXIT_CONN_STATE_CONNECTING states. */
|
|
|
|
|
|
tor_assert(cell);
|
|
|
tor_assert(circ);
|
|
@@ -1050,9 +1053,20 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
|
|
/* either conn is NULL, in which case we've got a control cell, or else
|
|
|
* conn points to the recognized stream. */
|
|
|
|
|
|
- if (conn && !connection_state_is_open(TO_CONN(conn)))
|
|
|
- return connection_edge_process_relay_cell_not_open(
|
|
|
- &rh, cell, circ, conn, layer_hint);
|
|
|
+ if (conn && !connection_state_is_open(TO_CONN(conn))) {
|
|
|
+ if (conn->_base.type == CONN_TYPE_EXIT &&
|
|
|
+ (conn->_base.state == EXIT_CONN_STATE_CONNECTING ||
|
|
|
+ conn->_base.state == EXIT_CONN_STATE_RESOLVING) &&
|
|
|
+ rh.command == RELAY_COMMAND_DATA) {
|
|
|
+ /* Allow DATA cells to be delivered to an exit node in state
|
|
|
+ * EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING.
|
|
|
+ * This speeds up HTTP, for example. */
|
|
|
+ optimistic_data = 1;
|
|
|
+ } else {
|
|
|
+ return connection_edge_process_relay_cell_not_open(
|
|
|
+ &rh, cell, circ, conn, layer_hint);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
switch (rh.command) {
|
|
|
case RELAY_COMMAND_DROP:
|
|
@@ -1119,7 +1133,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
|
|
stats_n_data_bytes_received += rh.length;
|
|
|
connection_write_to_buf((char*)(cell->payload + RELAY_HEADER_SIZE),
|
|
|
rh.length, TO_CONN(conn));
|
|
|
- connection_edge_consider_sending_sendme(conn);
|
|
|
+
|
|
|
+ if (!optimistic_data) {
|
|
|
+ /* Only send a SENDME if we're not getting optimistic data; otherwise
|
|
|
+ * a SENDME could arrive before the CONNECTED.
|
|
|
+ */
|
|
|
+ connection_edge_consider_sending_sendme(conn);
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
case RELAY_COMMAND_END:
|
|
|
reason = rh.length > 0 ?
|