test_channeltls.c 8.8 KB

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