Line data Source code
1 : /* Copyright (c) 2007-2021, The Tor Project, Inc. */ 2 : /* See LICENSE for licensing information */ 3 : 4 : /** 5 : * \file btrack_orconn_cevent.c 6 : * \brief Emit bootstrap status events for OR connections 7 : * 8 : * We do some decoding of the raw OR_CONN_STATE_* values. For 9 : * example, OR_CONN_STATE_CONNECTING means the first TCP connect() 10 : * completing, regardless of whether it's directly to a relay instead 11 : * of a proxy or a PT. 12 : **/ 13 : 14 : #include <stdbool.h> 15 : 16 : #include "core/or/or.h" 17 : 18 : #define BTRACK_ORCONN_PRIVATE 19 : 20 : #include "core/or/orconn_event.h" 21 : #include "feature/control/btrack_orconn.h" 22 : #include "feature/control/btrack_orconn_cevent.h" 23 : #include "feature/control/control_events.h" 24 : 25 : /** 26 : * Have we completed our first OR connection? 27 : * 28 : * Block display of application circuit progress until we do, to avoid 29 : * some misleading behavior of jumping to high progress. 30 : **/ 31 : static bool bto_first_orconn = false; 32 : 33 : /** Is the ORCONN using a pluggable transport? */ 34 : static bool 35 11 : using_pt(const bt_orconn_t *bto) 36 : { 37 11 : return bto->proxy_type == PROXY_PLUGGABLE; 38 : } 39 : 40 : /** Is the ORCONN using a non-PT proxy? */ 41 : static bool 42 7 : using_proxy(const bt_orconn_t *bto) 43 : { 44 7 : switch (bto->proxy_type) { 45 : case PROXY_CONNECT: 46 : case PROXY_SOCKS4: 47 : case PROXY_SOCKS5: 48 : case PROXY_HAPROXY: 49 : return true; 50 3 : default: 51 3 : return false; 52 : } 53 : } 54 : 55 : /** 56 : * Emit control events when we have updated our idea of the best state 57 : * that any OR connection has reached. 58 : * 59 : * Do some decoding of the ORCONN states depending on whether a PT or 60 : * a proxy is in use. 61 : **/ 62 : void 63 17 : bto_cevent_anyconn(const bt_orconn_t *bto) 64 : { 65 17 : switch (bto->state) { 66 4 : case OR_CONN_STATE_CONNECTING: 67 : /* Exactly what kind of thing we're connecting to isn't 68 : * information we directly get from the states in connection_or.c, 69 : * so decode it here. */ 70 4 : if (using_pt(bto)) 71 1 : control_event_bootstrap(BOOTSTRAP_STATUS_CONN_PT, 0); 72 3 : else if (using_proxy(bto)) 73 1 : control_event_bootstrap(BOOTSTRAP_STATUS_CONN_PROXY, 0); 74 : else 75 2 : control_event_bootstrap(BOOTSTRAP_STATUS_CONN, 0); 76 : break; 77 2 : case OR_CONN_STATE_PROXY_HANDSHAKING: 78 : /* Similarly, starting a proxy handshake means the TCP connect() 79 : * succeeded to the proxy. Let's be specific about what kind of 80 : * proxy. */ 81 2 : if (using_pt(bto)) 82 1 : control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DONE_PT, 0); 83 1 : else if (using_proxy(bto)) 84 1 : control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DONE_PROXY, 0); 85 : break; 86 3 : case OR_CONN_STATE_TLS_HANDSHAKING: 87 3 : control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DONE, 0); 88 3 : break; 89 3 : case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING: 90 : case OR_CONN_STATE_OR_HANDSHAKING_V2: 91 : case OR_CONN_STATE_OR_HANDSHAKING_V3: 92 3 : control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0); 93 3 : break; 94 3 : case OR_CONN_STATE_OPEN: 95 3 : control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE_DONE, 0); 96 : /* Unblock directory progress display */ 97 3 : control_event_boot_first_orconn(); 98 : /* Unblock apconn progress display */ 99 3 : bto_first_orconn = true; 100 3 : break; 101 : default: 102 : break; 103 : } 104 17 : } 105 : 106 : /** 107 : * Emit control events when we have updated our idea of the best state 108 : * that any application circuit OR connection has reached. 109 : * 110 : * Do some decoding of the ORCONN states depending on whether a PT or 111 : * a proxy is in use. 112 : **/ 113 : void 114 11 : bto_cevent_apconn(const bt_orconn_t *bto) 115 : { 116 11 : if (!bto_first_orconn) 117 : return; 118 : 119 10 : switch (bto->state) { 120 3 : case OR_CONN_STATE_CONNECTING: 121 : /* Exactly what kind of thing we're connecting to isn't 122 : * information we directly get from the states in connection_or.c, 123 : * so decode it here. */ 124 3 : if (using_pt(bto)) 125 1 : control_event_bootstrap(BOOTSTRAP_STATUS_AP_CONN_PT, 0); 126 2 : else if (using_proxy(bto)) 127 1 : control_event_bootstrap(BOOTSTRAP_STATUS_AP_CONN_PROXY, 0); 128 : else 129 1 : control_event_bootstrap(BOOTSTRAP_STATUS_AP_CONN, 0); 130 : break; 131 2 : case OR_CONN_STATE_PROXY_HANDSHAKING: 132 : /* Similarly, starting a proxy handshake means the TCP connect() 133 : * succeeded to the proxy. Let's be specific about what kind of 134 : * proxy. */ 135 2 : if (using_pt(bto)) 136 1 : control_event_bootstrap(BOOTSTRAP_STATUS_AP_CONN_DONE_PT, 0); 137 1 : else if (using_proxy(bto)) 138 1 : control_event_bootstrap(BOOTSTRAP_STATUS_AP_CONN_DONE_PROXY, 0); 139 : break; 140 1 : case OR_CONN_STATE_TLS_HANDSHAKING: 141 1 : control_event_bootstrap(BOOTSTRAP_STATUS_AP_CONN_DONE, 0); 142 1 : break; 143 1 : case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING: 144 : case OR_CONN_STATE_OR_HANDSHAKING_V2: 145 : case OR_CONN_STATE_OR_HANDSHAKING_V3: 146 1 : control_event_bootstrap(BOOTSTRAP_STATUS_AP_HANDSHAKE, 0); 147 1 : break; 148 1 : case OR_CONN_STATE_OPEN: 149 1 : control_event_bootstrap(BOOTSTRAP_STATUS_AP_HANDSHAKE_DONE, 0); 150 1 : break; 151 : default: 152 : break; 153 : } 154 : } 155 : 156 : /** Forget that we completed our first OR connection */ 157 : void 158 235 : bto_cevent_reset(void) 159 : { 160 235 : bto_first_orconn = false; 161 235 : }