| 1908 | |
| 1909 | |
| 1910 | void SocketManager::send_connect( |
| 1911 | const Future<Nothing>& future, |
| 1912 | Socket socket, |
| 1913 | Message&& message) |
| 1914 | { |
| 1915 | if (future.isDiscarded() || future.isFailed()) { |
| 1916 | if (future.isFailed()) { |
| 1917 | LOG(WARNING) << "Failed to send '" << message.name << "' to '" |
| 1918 | << message.to.address << "', connect: " << future.failure(); |
| 1919 | } |
| 1920 | |
| 1921 | // Check if SSL is enabled, and whether we allow a downgrade to |
| 1922 | // non-SSL traffic. |
| 1923 | #ifdef USE_SSL_SOCKET |
| 1924 | bool attempt_downgrade = |
| 1925 | future.isFailed() && |
| 1926 | network::openssl::flags().enabled && |
| 1927 | network::openssl::flags().support_downgrade && |
| 1928 | socket.kind() == SocketImpl::Kind::SSL; |
| 1929 | |
| 1930 | Option<Socket> poll_socket = None(); |
| 1931 | |
| 1932 | // If we allow downgrading from SSL to non-SSL, then retry as a |
| 1933 | // POLL socket. |
| 1934 | if (attempt_downgrade) { |
| 1935 | synchronized (mutex) { |
| 1936 | Try<Socket> create = Socket::create(SocketImpl::Kind::POLL); |
| 1937 | if (create.isError()) { |
| 1938 | LOG(WARNING) << "Failed to link to '" << message.to.address |
| 1939 | << "', create socket: " << create.error(); |
| 1940 | socket_manager->close(socket); |
| 1941 | return; |
| 1942 | } |
| 1943 | |
| 1944 | poll_socket = create.get(); |
| 1945 | |
| 1946 | // Update all the data structures that are mapped to the socket |
| 1947 | // that just failed to connect. They will now point to the new |
| 1948 | // POLL socket we are about to try to connect. Even if the |
| 1949 | // process has exited, persistent links will stay around, and |
| 1950 | // temporary links will get cleaned up as they would otherwise. |
| 1951 | swap_implementing_socket(socket, poll_socket.get()); |
| 1952 | } |
| 1953 | |
| 1954 | CHECK_SOME(poll_socket); |
| 1955 | Future<Nothing> connect = poll_socket->connect(message.to.address); |
| 1956 | connect.onAny(lambda::bind( |
| 1957 | // TODO(benh): with C++14 we can use lambda instead of |
| 1958 | // `std::bind` and capture `message` with a `std::move`. |
| 1959 | [this, poll_socket](Message& message, const Future<Nothing>& f) { |
| 1960 | send_connect(f, poll_socket.get(), std::move(message)); |
| 1961 | }, |
| 1962 | std::move(message), |
| 1963 | lambda::_1)); |
| 1964 | |
| 1965 | // We don't need to 'shutdown()' the socket as it was never |
| 1966 | // connected. |
| 1967 | return; |