Refactor HandshakeHelper and add a peeking handshake helper
authorSubodh Iyengar <subodh@fb.com>
Tue, 18 Aug 2015 04:28:08 +0000 (21:28 -0700)
committerfacebook-github-bot-1 <folly-bot@fb.com>
Tue, 18 Aug 2015 05:20:17 +0000 (22:20 -0700)
Summary: This adds support to Acceptor to be able to switch between
multiple protcols when SSL is being negotiated using MSG_PEEK.

The motivation for this is to be able to try out multiple protocols.

Reviewed By: @djwatson

Differential Revision: D2327946

folly/io/async/AsyncSocket.cpp
folly/io/async/AsyncSocket.h
folly/io/async/test/MockAsyncSSLSocket.h

index 9df09eb2b3c1944389aad6402038a4db4a154460..e7c9c4510499da09cb3a16e0d57c330825bcd8eb 100644 (file)
@@ -1235,7 +1235,12 @@ ssize_t AsyncSocket::performRead(void** buf, size_t* buflen, size_t* offset) {
   VLOG(5) << "AsyncSocket::performRead() this=" << this
           << ", buf=" << *buf << ", buflen=" << *buflen;
 
-  ssize_t bytes = recv(fd_, *buf, *buflen, MSG_DONTWAIT);
+  int recvFlags = 0;
+  if (peek_) {
+    recvFlags |= MSG_PEEK;
+  }
+
+  ssize_t bytes = recv(fd_, *buf, *buflen, MSG_DONTWAIT | recvFlags);
   if (bytes < 0) {
     if (errno == EAGAIN || errno == EWOULDBLOCK) {
       // No more data to read right now.
index 38939ee786e908dbc11dadcd453292cb84e32ba7..17e87796f0cbefaa7e79a3ae2dc7022424821827 100644 (file)
@@ -475,6 +475,10 @@ class AsyncSocket : virtual public AsyncTransportWrapper {
     return setsockopt(fd_, level, optname, optval, sizeof(T));
   }
 
+  virtual void setPeek(bool peek) {
+    peek_ = peek;
+  }
+
   enum class StateEnum : uint8_t {
     UNINIT,
     CONNECTING,
@@ -764,6 +768,8 @@ class AsyncSocket : virtual public AsyncTransportWrapper {
   size_t appBytesReceived_;             ///< Num of bytes received from socket
   size_t appBytesWritten_;              ///< Num of bytes written to socket
   bool isBufferMovable_{false};
+
+  bool peek_{false}; // Peek bytes.
 };
 
 
index 47df2f77151d2c34a3d62f64767d61230aabba7f..ff9456c65be1fa50ec9ebe7d9eaa3f0531e2e36f 100644 (file)
@@ -24,8 +24,9 @@ class MockAsyncSSLSocket : public AsyncSSLSocket {
  public:
   MockAsyncSSLSocket(
    const std::shared_ptr<SSLContext>& ctx,
-   EventBase* base) :
-    AsyncSSLSocket(ctx, base) {
+   EventBase* base,
+   bool deferSecurityNegotiation = false) :
+    AsyncSSLSocket(ctx, base, deferSecurityNegotiation) {
   }
 
   GMOCK_METHOD5_(, noexcept, ,
@@ -47,6 +48,8 @@ class MockAsyncSSLSocket : public AsyncSSLSocket {
   MOCK_CONST_METHOD2(
    getSelectedNextProtocolNoThrow,
    bool(const unsigned char**, unsigned*));
+  MOCK_METHOD1(setPeek, void(bool));
+  MOCK_METHOD1(setReadCB, void(ReadCallback*));
 
   void sslConn(
     AsyncSSLSocket::HandshakeCB* cb,
@@ -63,10 +66,32 @@ class MockAsyncSSLSocket : public AsyncSSLSocket {
 
     sslConnectMockable(cb, timeout, verify);
   }
+
+  void sslAccept(
+    AsyncSSLSocket::HandshakeCB* cb,
+    uint32_t timeout,
+    const SSLContext::SSLVerifyPeerEnum& verify)
+      override {
+    if (timeout > 0) {
+      handshakeTimeout_.scheduleTimeout(timeout);
+    }
+
+    state_ = StateEnum::ESTABLISHED;
+    sslState_ = STATE_ACCEPTING;
+    handshakeCallback_ = cb;
+
+    sslAcceptMockable(cb, timeout, verify);
+  }
+
   MOCK_METHOD3(
    sslConnectMockable,
    void(AsyncSSLSocket::HandshakeCB*, uint64_t,
      const SSLContext::SSLVerifyPeerEnum&));
+
+  MOCK_METHOD3(
+   sslAcceptMockable,
+   void(AsyncSSLSocket::HandshakeCB*, uint32_t,
+     const SSLContext::SSLVerifyPeerEnum&));
 };
 
 }}