AsyncSSLSocketWriteTest.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*
  2. * Copyright 2013-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/io/Cursor.h>
  17. #include <folly/io/async/AsyncSSLSocket.h>
  18. #include <folly/io/async/AsyncSocket.h>
  19. #include <folly/io/async/EventBase.h>
  20. #include <folly/portability/GMock.h>
  21. #include <folly/portability/GTest.h>
  22. #include <string>
  23. #include <vector>
  24. using std::string;
  25. using namespace testing;
  26. namespace folly {
  27. class MockAsyncSSLSocket : public AsyncSSLSocket {
  28. public:
  29. static std::shared_ptr<MockAsyncSSLSocket> newSocket(
  30. const std::shared_ptr<SSLContext>& ctx,
  31. EventBase* evb) {
  32. auto sock = std::shared_ptr<MockAsyncSSLSocket>(
  33. new MockAsyncSSLSocket(ctx, evb), Destructor());
  34. sock->ssl_.reset(SSL_new(ctx->getSSLCtx()));
  35. SSL_set_fd(sock->ssl_.get(), -1);
  36. return sock;
  37. }
  38. // Fake constructor sets the state to established without call to connect
  39. // or accept
  40. MockAsyncSSLSocket(const std::shared_ptr<SSLContext>& ctx, EventBase* evb)
  41. : AsyncSocket(evb), AsyncSSLSocket(ctx, evb) {
  42. state_ = AsyncSocket::StateEnum::ESTABLISHED;
  43. sslState_ = AsyncSSLSocket::SSLStateEnum::STATE_ESTABLISHED;
  44. }
  45. // mock the calls to SSL_write to see the buffer length and contents
  46. MOCK_METHOD3(sslWriteImpl, int(SSL* ssl, const void* buf, int n));
  47. // mock the calls to getRawBytesWritten()
  48. MOCK_CONST_METHOD0(getRawBytesWritten, size_t());
  49. // public wrapper for protected interface
  50. WriteResult testPerformWrite(
  51. const iovec* vec,
  52. uint32_t count,
  53. WriteFlags flags,
  54. uint32_t* countWritten,
  55. uint32_t* partialWritten) {
  56. return performWrite(vec, count, flags, countWritten, partialWritten);
  57. }
  58. void checkEor(size_t appEor, size_t rawEor) {
  59. EXPECT_EQ(appEor, appEorByteNo_);
  60. EXPECT_EQ(rawEor, minEorRawByteNo_);
  61. }
  62. void setAppBytesWritten(size_t n) {
  63. appBytesWritten_ = n;
  64. }
  65. };
  66. class AsyncSSLSocketWriteTest : public testing::Test {
  67. public:
  68. AsyncSSLSocketWriteTest()
  69. : sslContext_(new SSLContext()),
  70. sock_(MockAsyncSSLSocket::newSocket(sslContext_, &eventBase_)) {
  71. for (int i = 0; i < 500; i++) {
  72. memcpy(source_ + i * 26, "abcdefghijklmnopqrstuvwxyz", 26);
  73. }
  74. }
  75. // Make an iovec containing chunks of the reference text with requested sizes
  76. // for each chunk
  77. std::unique_ptr<iovec[]> makeVec(std::vector<uint32_t> sizes) {
  78. std::unique_ptr<iovec[]> vec(new iovec[sizes.size()]);
  79. int i = 0;
  80. int pos = 0;
  81. for (auto size : sizes) {
  82. vec[i].iov_base = (void*)(source_ + pos);
  83. vec[i++].iov_len = size;
  84. pos += size;
  85. }
  86. return vec;
  87. }
  88. // Verify that the given buf/pos matches the reference text
  89. void verifyVec(const void* buf, int n, int pos) {
  90. ASSERT_EQ(memcmp(source_ + pos, buf, n), 0);
  91. }
  92. // Update a vec on partial write
  93. void consumeVec(iovec* vec, uint32_t countWritten, uint32_t partialWritten) {
  94. vec[countWritten].iov_base =
  95. ((char*)vec[countWritten].iov_base) + partialWritten;
  96. vec[countWritten].iov_len -= partialWritten;
  97. }
  98. EventBase eventBase_;
  99. std::shared_ptr<SSLContext> sslContext_;
  100. std::shared_ptr<MockAsyncSSLSocket> sock_;
  101. char source_[26 * 500];
  102. };
  103. // The entire vec fits in one packet
  104. TEST_F(AsyncSSLSocketWriteTest, write_coalescing1) {
  105. int n = 3;
  106. auto vec = makeVec({3, 3, 3});
  107. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 9))
  108. .WillOnce(Invoke([this](SSL*, const void* buf, int m) {
  109. verifyVec(buf, m, 0);
  110. return 9;
  111. }));
  112. uint32_t countWritten = 0;
  113. uint32_t partialWritten = 0;
  114. sock_->testPerformWrite(
  115. vec.get(), n, WriteFlags::NONE, &countWritten, &partialWritten);
  116. EXPECT_EQ(countWritten, n);
  117. EXPECT_EQ(partialWritten, 0);
  118. }
  119. // First packet is full, second two go in one packet
  120. TEST_F(AsyncSSLSocketWriteTest, write_coalescing2) {
  121. int n = 3;
  122. auto vec = makeVec({1500, 3, 3});
  123. int pos = 0;
  124. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 1500))
  125. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  126. verifyVec(buf, m, pos);
  127. pos += m;
  128. return m;
  129. }));
  130. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 6))
  131. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  132. verifyVec(buf, m, pos);
  133. pos += m;
  134. return m;
  135. }));
  136. uint32_t countWritten = 0;
  137. uint32_t partialWritten = 0;
  138. sock_->testPerformWrite(
  139. vec.get(), n, WriteFlags::NONE, &countWritten, &partialWritten);
  140. EXPECT_EQ(countWritten, n);
  141. EXPECT_EQ(partialWritten, 0);
  142. }
  143. // Two exactly full packets (coalesce ends midway through second chunk)
  144. TEST_F(AsyncSSLSocketWriteTest, write_coalescing3) {
  145. int n = 3;
  146. auto vec = makeVec({1000, 1000, 1000});
  147. int pos = 0;
  148. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 1500))
  149. .Times(2)
  150. .WillRepeatedly(Invoke([this, &pos](SSL*, const void* buf, int m) {
  151. verifyVec(buf, m, pos);
  152. pos += m;
  153. return m;
  154. }));
  155. uint32_t countWritten = 0;
  156. uint32_t partialWritten = 0;
  157. sock_->testPerformWrite(
  158. vec.get(), n, WriteFlags::NONE, &countWritten, &partialWritten);
  159. EXPECT_EQ(countWritten, n);
  160. EXPECT_EQ(partialWritten, 0);
  161. }
  162. // Partial write success midway through a coalesced vec
  163. TEST_F(AsyncSSLSocketWriteTest, write_coalescing4) {
  164. int n = 5;
  165. auto vec = makeVec({300, 300, 300, 300, 300});
  166. int pos = 0;
  167. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 1500))
  168. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  169. verifyVec(buf, m, pos);
  170. pos += 1000;
  171. return 1000; /* 500 bytes "pending" */
  172. }));
  173. uint32_t countWritten = 0;
  174. uint32_t partialWritten = 0;
  175. sock_->testPerformWrite(
  176. vec.get(), n, WriteFlags::NONE, &countWritten, &partialWritten);
  177. EXPECT_EQ(countWritten, 3);
  178. EXPECT_EQ(partialWritten, 100);
  179. consumeVec(vec.get(), countWritten, partialWritten);
  180. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 500))
  181. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  182. verifyVec(buf, m, pos);
  183. pos += m;
  184. return 500;
  185. }));
  186. sock_->testPerformWrite(
  187. vec.get() + countWritten,
  188. n - countWritten,
  189. WriteFlags::NONE,
  190. &countWritten,
  191. &partialWritten);
  192. EXPECT_EQ(countWritten, 2);
  193. EXPECT_EQ(partialWritten, 0);
  194. }
  195. // coalesce ends exactly on a buffer boundary
  196. TEST_F(AsyncSSLSocketWriteTest, write_coalescing5) {
  197. int n = 3;
  198. auto vec = makeVec({1000, 500, 500});
  199. int pos = 0;
  200. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 1500))
  201. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  202. verifyVec(buf, m, pos);
  203. pos += m;
  204. return m;
  205. }));
  206. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 500))
  207. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  208. verifyVec(buf, m, pos);
  209. pos += m;
  210. return m;
  211. }));
  212. uint32_t countWritten = 0;
  213. uint32_t partialWritten = 0;
  214. sock_->testPerformWrite(
  215. vec.get(), n, WriteFlags::NONE, &countWritten, &partialWritten);
  216. EXPECT_EQ(countWritten, 3);
  217. EXPECT_EQ(partialWritten, 0);
  218. }
  219. // partial write midway through first chunk
  220. TEST_F(AsyncSSLSocketWriteTest, write_coalescing6) {
  221. int n = 2;
  222. auto vec = makeVec({1000, 500});
  223. int pos = 0;
  224. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 1500))
  225. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  226. verifyVec(buf, m, pos);
  227. pos += 700;
  228. return 700;
  229. }));
  230. uint32_t countWritten = 0;
  231. uint32_t partialWritten = 0;
  232. sock_->testPerformWrite(
  233. vec.get(), n, WriteFlags::NONE, &countWritten, &partialWritten);
  234. EXPECT_EQ(countWritten, 0);
  235. EXPECT_EQ(partialWritten, 700);
  236. consumeVec(vec.get(), countWritten, partialWritten);
  237. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 800))
  238. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  239. verifyVec(buf, m, pos);
  240. pos += m;
  241. return m;
  242. }));
  243. sock_->testPerformWrite(
  244. vec.get() + countWritten,
  245. n - countWritten,
  246. WriteFlags::NONE,
  247. &countWritten,
  248. &partialWritten);
  249. EXPECT_EQ(countWritten, 2);
  250. EXPECT_EQ(partialWritten, 0);
  251. }
  252. // Repeat coalescing2 with WriteFlags::EOR
  253. TEST_F(AsyncSSLSocketWriteTest, write_with_eor1) {
  254. int n = 3;
  255. auto vec = makeVec({1500, 3, 3});
  256. int pos = 0;
  257. const size_t initAppBytesWritten = 500;
  258. const size_t appEor = initAppBytesWritten + 1506;
  259. sock_->setAppBytesWritten(initAppBytesWritten);
  260. EXPECT_FALSE(sock_->isEorTrackingEnabled());
  261. sock_->setEorTracking(true);
  262. EXPECT_TRUE(sock_->isEorTrackingEnabled());
  263. EXPECT_CALL(*(sock_.get()), getRawBytesWritten())
  264. // rawBytesWritten after writting initAppBytesWritten + 1500
  265. // + some random SSL overhead
  266. .WillOnce(Return(3600u))
  267. // rawBytesWritten after writting last 6 bytes
  268. // + some random SSL overhead
  269. .WillOnce(Return(3728u));
  270. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 1500))
  271. .WillOnce(Invoke([=, &pos](SSL*, const void* buf, int m) {
  272. // the first 1500 does not have the EOR byte
  273. sock_->checkEor(0, 0);
  274. verifyVec(buf, m, pos);
  275. pos += m;
  276. return m;
  277. }));
  278. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 6))
  279. .WillOnce(Invoke([=, &pos](SSL*, const void* buf, int m) {
  280. sock_->checkEor(appEor, 3600 + m);
  281. verifyVec(buf, m, pos);
  282. pos += m;
  283. return m;
  284. }));
  285. uint32_t countWritten = 0;
  286. uint32_t partialWritten = 0;
  287. sock_->testPerformWrite(
  288. vec.get(), n, WriteFlags::EOR, &countWritten, &partialWritten);
  289. EXPECT_EQ(countWritten, n);
  290. EXPECT_EQ(partialWritten, 0);
  291. sock_->checkEor(0, 0);
  292. }
  293. // coalescing with left over at the last chunk
  294. // WriteFlags::EOR turned on
  295. TEST_F(AsyncSSLSocketWriteTest, write_with_eor2) {
  296. int n = 3;
  297. auto vec = makeVec({600, 600, 600});
  298. int pos = 0;
  299. const size_t initAppBytesWritten = 500;
  300. const size_t appEor = initAppBytesWritten + 1800;
  301. sock_->setAppBytesWritten(initAppBytesWritten);
  302. sock_->setEorTracking(true);
  303. EXPECT_CALL(*(sock_.get()), getRawBytesWritten())
  304. // rawBytesWritten after writting initAppBytesWritten + 1500 bytes
  305. // + some random SSL overhead
  306. .WillOnce(Return(3600))
  307. // rawBytesWritten after writting last 300 bytes
  308. // + some random SSL overhead
  309. .WillOnce(Return(4100));
  310. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 1500))
  311. .WillOnce(Invoke([=, &pos](SSL*, const void* buf, int m) {
  312. // the first 1500 does not have the EOR byte
  313. sock_->checkEor(0, 0);
  314. verifyVec(buf, m, pos);
  315. pos += m;
  316. return m;
  317. }));
  318. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 300))
  319. .WillOnce(Invoke([=, &pos](SSL*, const void* buf, int m) {
  320. sock_->checkEor(appEor, 3600 + m);
  321. verifyVec(buf, m, pos);
  322. pos += m;
  323. return m;
  324. }));
  325. uint32_t countWritten = 0;
  326. uint32_t partialWritten = 0;
  327. sock_->testPerformWrite(
  328. vec.get(), n, WriteFlags::EOR, &countWritten, &partialWritten);
  329. EXPECT_EQ(countWritten, n);
  330. EXPECT_EQ(partialWritten, 0);
  331. sock_->checkEor(0, 0);
  332. }
  333. // WriteFlags::EOR set
  334. // One buf in iovec
  335. // Partial write at 1000-th byte
  336. TEST_F(AsyncSSLSocketWriteTest, write_with_eor3) {
  337. int n = 1;
  338. auto vec = makeVec({1600});
  339. int pos = 0;
  340. static constexpr size_t initAppBytesWritten = 500;
  341. static constexpr size_t appEor = initAppBytesWritten + 1600;
  342. sock_->setAppBytesWritten(initAppBytesWritten);
  343. sock_->setEorTracking(true);
  344. EXPECT_CALL(*(sock_.get()), getRawBytesWritten())
  345. // rawBytesWritten after the initAppBytesWritten
  346. // + some random SSL overhead
  347. .WillOnce(Return(2000))
  348. // rawBytesWritten after the initAppBytesWritten + 1000 (with 100
  349. // overhead)
  350. // + some random SSL overhead
  351. .WillOnce(Return(3100));
  352. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 1600))
  353. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  354. sock_->checkEor(appEor, 2000 + m);
  355. verifyVec(buf, m, pos);
  356. pos += 1000;
  357. return 1000;
  358. }));
  359. uint32_t countWritten = 0;
  360. uint32_t partialWritten = 0;
  361. sock_->testPerformWrite(
  362. vec.get(), n, WriteFlags::EOR, &countWritten, &partialWritten);
  363. EXPECT_EQ(countWritten, 0);
  364. EXPECT_EQ(partialWritten, 1000);
  365. sock_->checkEor(appEor, 2000 + 1600);
  366. consumeVec(vec.get(), countWritten, partialWritten);
  367. EXPECT_CALL(*(sock_.get()), getRawBytesWritten())
  368. .WillOnce(Return(3100))
  369. .WillOnce(Return(3800));
  370. EXPECT_CALL(*(sock_.get()), sslWriteImpl(_, _, 600))
  371. .WillOnce(Invoke([this, &pos](SSL*, const void* buf, int m) {
  372. sock_->checkEor(appEor, 3100 + m);
  373. verifyVec(buf, m, pos);
  374. pos += m;
  375. return m;
  376. }));
  377. sock_->testPerformWrite(
  378. vec.get() + countWritten,
  379. n - countWritten,
  380. WriteFlags::EOR,
  381. &countWritten,
  382. &partialWritten);
  383. EXPECT_EQ(countWritten, n);
  384. EXPECT_EQ(partialWritten, 0);
  385. sock_->checkEor(0, 0);
  386. }
  387. } // namespace folly