test_channeltls.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /* Copyright (c) 2014-2016, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "orconfig.h"
  4. #include <math.h>
  5. #define TOR_CHANNEL_INTERNAL_
  6. #include "or.h"
  7. #include "address.h"
  8. #include "buffers.h"
  9. #include "channel.h"
  10. #include "channeltls.h"
  11. #include "connection_or.h"
  12. #include "config.h"
  13. /* For init/free stuff */
  14. #include "scheduler.h"
  15. #include "tortls.h"
  16. /* Test suite stuff */
  17. #include "test.h"
  18. #include "fakechans.h"
  19. /* The channeltls unit tests */
  20. static void test_channeltls_create(void *arg);
  21. static void test_channeltls_num_bytes_queued(void *arg);
  22. static void test_channeltls_overhead_estimate(void *arg);
  23. /* Mocks used by channeltls unit tests */
  24. static size_t tlschan_buf_datalen_mock(const buf_t *buf);
  25. static or_connection_t * tlschan_connection_or_connect_mock(
  26. const tor_addr_t *addr,
  27. uint16_t port,
  28. const char *digest,
  29. channel_tls_t *tlschan);
  30. static int tlschan_is_local_addr_mock(const tor_addr_t *addr);
  31. /* Fake close method */
  32. static void tlschan_fake_close_method(channel_t *chan);
  33. /* Flags controlling behavior of channeltls unit test mocks */
  34. static int tlschan_local = 0;
  35. static const buf_t * tlschan_buf_datalen_mock_target = NULL;
  36. static size_t tlschan_buf_datalen_mock_size = 0;
  37. /* Thing to cast to fake tor_tls_t * to appease assert_connection_ok() */
  38. static int fake_tortls = 0; /* Bleh... */
  39. static void
  40. test_channeltls_create(void *arg)
  41. {
  42. tor_addr_t test_addr;
  43. channel_t *ch = NULL;
  44. const char test_digest[DIGEST_LEN] = {
  45. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
  46. 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
  47. (void)arg;
  48. /* Set up a fake address to fake-connect to */
  49. test_addr.family = AF_INET;
  50. test_addr.addr.in_addr.s_addr = htonl(0x01020304);
  51. /* For this test we always want the address to be treated as non-local */
  52. tlschan_local = 0;
  53. /* Install is_local_addr() mock */
  54. MOCK(is_local_addr, tlschan_is_local_addr_mock);
  55. /* Install mock for connection_or_connect() */
  56. MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
  57. /* Try connecting */
  58. ch = channel_tls_connect(&test_addr, 567, test_digest);
  59. tt_assert(ch != NULL);
  60. done:
  61. if (ch) {
  62. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  63. /*
  64. * Use fake close method that doesn't try to do too much to fake
  65. * orconn
  66. */
  67. ch->close = tlschan_fake_close_method;
  68. channel_mark_for_close(ch);
  69. free_fake_channel(ch);
  70. UNMOCK(scheduler_release_channel);
  71. }
  72. UNMOCK(connection_or_connect);
  73. UNMOCK(is_local_addr);
  74. return;
  75. }
  76. static void
  77. test_channeltls_num_bytes_queued(void *arg)
  78. {
  79. tor_addr_t test_addr;
  80. channel_t *ch = NULL;
  81. const char test_digest[DIGEST_LEN] = {
  82. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
  83. 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
  84. channel_tls_t *tlschan = NULL;
  85. size_t len;
  86. int fake_outbuf = 0, n;
  87. (void)arg;
  88. /* Set up a fake address to fake-connect to */
  89. test_addr.family = AF_INET;
  90. test_addr.addr.in_addr.s_addr = htonl(0x01020304);
  91. /* For this test we always want the address to be treated as non-local */
  92. tlschan_local = 0;
  93. /* Install is_local_addr() mock */
  94. MOCK(is_local_addr, tlschan_is_local_addr_mock);
  95. /* Install mock for connection_or_connect() */
  96. MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
  97. /* Try connecting */
  98. ch = channel_tls_connect(&test_addr, 567, test_digest);
  99. tt_assert(ch != NULL);
  100. /*
  101. * Next, we have to test ch->num_bytes_queued, which is
  102. * channel_tls_num_bytes_queued_method. We can't mock
  103. * connection_get_outbuf_len() directly because it's static inline
  104. * in connection.h, but we can mock buf_datalen(). Note that
  105. * if bufferevents ever work, this will break with them enabled.
  106. */
  107. tt_assert(ch->num_bytes_queued != NULL);
  108. tlschan = BASE_CHAN_TO_TLS(ch);
  109. tt_assert(tlschan != NULL);
  110. if (TO_CONN(tlschan->conn)->outbuf == NULL) {
  111. /* We need an outbuf to make sure buf_datalen() gets called */
  112. fake_outbuf = 1;
  113. TO_CONN(tlschan->conn)->outbuf = buf_new();
  114. }
  115. tlschan_buf_datalen_mock_target = TO_CONN(tlschan->conn)->outbuf;
  116. tlschan_buf_datalen_mock_size = 1024;
  117. MOCK(buf_datalen, tlschan_buf_datalen_mock);
  118. len = ch->num_bytes_queued(ch);
  119. tt_int_op(len, ==, tlschan_buf_datalen_mock_size);
  120. /*
  121. * We also cover num_cells_writeable here; since wide_circ_ids = 0 on
  122. * the fake tlschans, cell_network_size returns 512, and so with
  123. * tlschan_buf_datalen_mock_size == 1024, we should be able to write
  124. * ceil((OR_CONN_HIGHWATER - 1024) / 512) = ceil(OR_CONN_HIGHWATER / 512)
  125. * - 2 cells.
  126. */
  127. n = ch->num_cells_writeable(ch);
  128. tt_int_op(n, ==, CEIL_DIV(OR_CONN_HIGHWATER, 512) - 2);
  129. UNMOCK(buf_datalen);
  130. tlschan_buf_datalen_mock_target = NULL;
  131. tlschan_buf_datalen_mock_size = 0;
  132. if (fake_outbuf) {
  133. buf_free(TO_CONN(tlschan->conn)->outbuf);
  134. TO_CONN(tlschan->conn)->outbuf = NULL;
  135. }
  136. done:
  137. if (ch) {
  138. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  139. /*
  140. * Use fake close method that doesn't try to do too much to fake
  141. * orconn
  142. */
  143. ch->close = tlschan_fake_close_method;
  144. channel_mark_for_close(ch);
  145. free_fake_channel(ch);
  146. UNMOCK(scheduler_release_channel);
  147. }
  148. UNMOCK(connection_or_connect);
  149. UNMOCK(is_local_addr);
  150. return;
  151. }
  152. static void
  153. test_channeltls_overhead_estimate(void *arg)
  154. {
  155. tor_addr_t test_addr;
  156. channel_t *ch = NULL;
  157. const char test_digest[DIGEST_LEN] = {
  158. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
  159. 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
  160. float r;
  161. channel_tls_t *tlschan = NULL;
  162. (void)arg;
  163. /* Set up a fake address to fake-connect to */
  164. test_addr.family = AF_INET;
  165. test_addr.addr.in_addr.s_addr = htonl(0x01020304);
  166. /* For this test we always want the address to be treated as non-local */
  167. tlschan_local = 0;
  168. /* Install is_local_addr() mock */
  169. MOCK(is_local_addr, tlschan_is_local_addr_mock);
  170. /* Install mock for connection_or_connect() */
  171. MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
  172. /* Try connecting */
  173. ch = channel_tls_connect(&test_addr, 567, test_digest);
  174. tt_assert(ch != NULL);
  175. /* First case: silly low ratios should get clamped to 1.0f */
  176. tlschan = BASE_CHAN_TO_TLS(ch);
  177. tt_assert(tlschan != NULL);
  178. tlschan->conn->bytes_xmitted = 128;
  179. tlschan->conn->bytes_xmitted_by_tls = 64;
  180. r = ch->get_overhead_estimate(ch);
  181. tt_assert(fabsf(r - 1.0f) < 1E-12);
  182. tlschan->conn->bytes_xmitted_by_tls = 127;
  183. r = ch->get_overhead_estimate(ch);
  184. tt_assert(fabsf(r - 1.0f) < 1E-12);
  185. /* Now middle of the range */
  186. tlschan->conn->bytes_xmitted_by_tls = 192;
  187. r = ch->get_overhead_estimate(ch);
  188. tt_assert(fabsf(r - 1.5f) < 1E-12);
  189. /* Now above the 2.0f clamp */
  190. tlschan->conn->bytes_xmitted_by_tls = 257;
  191. r = ch->get_overhead_estimate(ch);
  192. tt_assert(fabsf(r - 2.0f) < 1E-12);
  193. tlschan->conn->bytes_xmitted_by_tls = 512;
  194. r = ch->get_overhead_estimate(ch);
  195. tt_assert(fabsf(r - 2.0f) < 1E-12);
  196. done:
  197. if (ch) {
  198. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  199. /*
  200. * Use fake close method that doesn't try to do too much to fake
  201. * orconn
  202. */
  203. ch->close = tlschan_fake_close_method;
  204. channel_mark_for_close(ch);
  205. free_fake_channel(ch);
  206. UNMOCK(scheduler_release_channel);
  207. }
  208. UNMOCK(connection_or_connect);
  209. UNMOCK(is_local_addr);
  210. return;
  211. }
  212. static size_t
  213. tlschan_buf_datalen_mock(const buf_t *buf)
  214. {
  215. if (buf != NULL && buf == tlschan_buf_datalen_mock_target) {
  216. return tlschan_buf_datalen_mock_size;
  217. } else {
  218. return buf_datalen__real(buf);
  219. }
  220. }
  221. static or_connection_t *
  222. tlschan_connection_or_connect_mock(const tor_addr_t *addr,
  223. uint16_t port,
  224. const char *digest,
  225. channel_tls_t *tlschan)
  226. {
  227. or_connection_t *result = NULL;
  228. tt_assert(addr != NULL);
  229. tt_assert(port != 0);
  230. tt_assert(digest != NULL);
  231. tt_assert(tlschan != NULL);
  232. /* Make a fake orconn */
  233. result = tor_malloc_zero(sizeof(*result));
  234. result->base_.magic = OR_CONNECTION_MAGIC;
  235. result->base_.state = OR_CONN_STATE_OPEN;
  236. result->base_.type = CONN_TYPE_OR;
  237. result->base_.socket_family = addr->family;
  238. result->base_.address = tor_strdup("<fake>");
  239. memcpy(&(result->base_.addr), addr, sizeof(tor_addr_t));
  240. result->base_.port = port;
  241. memcpy(result->identity_digest, digest, DIGEST_LEN);
  242. result->chan = tlschan;
  243. memcpy(&(result->real_addr), addr, sizeof(tor_addr_t));
  244. result->tls = (tor_tls_t *)((void *)(&fake_tortls));
  245. done:
  246. return result;
  247. }
  248. static void
  249. tlschan_fake_close_method(channel_t *chan)
  250. {
  251. channel_tls_t *tlschan = NULL;
  252. tt_assert(chan != NULL);
  253. tt_int_op(chan->magic, ==, TLS_CHAN_MAGIC);
  254. tlschan = BASE_CHAN_TO_TLS(chan);
  255. tt_assert(tlschan != NULL);
  256. /* Just free the fake orconn */
  257. tor_free(tlschan->conn->base_.address);
  258. tor_free(tlschan->conn);
  259. channel_closed(chan);
  260. done:
  261. return;
  262. }
  263. static int
  264. tlschan_is_local_addr_mock(const tor_addr_t *addr)
  265. {
  266. tt_assert(addr != NULL);
  267. done:
  268. return tlschan_local;
  269. }
  270. struct testcase_t channeltls_tests[] = {
  271. { "create", test_channeltls_create, TT_FORK, NULL, NULL },
  272. { "num_bytes_queued", test_channeltls_num_bytes_queued,
  273. TT_FORK, NULL, NULL },
  274. { "overhead_estimate", test_channeltls_overhead_estimate,
  275. TT_FORK, NULL, NULL },
  276. END_OF_TESTCASES
  277. };