Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59a67a50 authored by Connor O'Brien's avatar Connor O'Brien Committed by Automerger Merge Worker
Browse files

Merge "Revert "Use abstract datachannels in Root Canal."" am: afb02ba5 am: 17803aa5

Original change: https://android-review.googlesource.com/c/platform/system/bt/+/1775327

Change-Id: I088b642c1f240a4544927a41cdf7cc2fecabf0d0
parents 4cab1133 17803aa5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ cc_library_static {
        "model/devices/keyboard.cc",
        "model/devices/link_layer_socket_device.cc",
        "model/devices/loopback.cc",
        "model/devices/polled_socket.cc",
        "model/devices/remote_loopback_device.cc",
        "model/devices/scripted_beacon.cc",
        "model/devices/sniffer.cc",
+10 −16
Original line number Diff line number Diff line
@@ -13,24 +13,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "test_environment.h"

#include <future>

#include <client/linux/handler/exception_handler.h>

#include <backtrace/Backtrace.h>
#include <backtrace/backtrace_constants.h>
#include <client/linux/handler/exception_handler.h>
#include <gflags/gflags.h>

#include <future>
#include <gflags/gflags.h>

#include "model/setup/async_manager.h"
#include "net/posix/posix_async_socket_connector.h"
#include "net/posix/posix_async_socket_server.h"
#include "os/log.h"

using ::android::bluetooth::root_canal::TestEnvironment;
using ::android::net::PosixAsyncSocketConnector;
using ::android::net::PosixAsyncSocketServer;
using test_vendor_lib::AsyncManager;

DEFINE_string(controller_properties_file, "",
              "controller_properties.json file path");
@@ -114,13 +111,10 @@ int main(int argc, char** argv) {
      }
    }
  }
  AsyncManager am;
  TestEnvironment root_canal(
      std::make_shared<PosixAsyncSocketServer>(test_port, &am),
      std::make_shared<PosixAsyncSocketServer>(hci_server_port, &am),
      std::make_shared<PosixAsyncSocketServer>(link_server_port, &am),
      std::make_shared<PosixAsyncSocketConnector>(&am),
      FLAGS_controller_properties_file, FLAGS_default_commands_file);

  TestEnvironment root_canal(test_port, hci_server_port, link_server_port,
                             FLAGS_controller_properties_file,
                             FLAGS_default_commands_file);
  std::promise<void> barrier;
  std::future<void> barrier_future = barrier.get_future();
  root_canal.initialize(std::move(barrier));
+117 −53
Original line number Diff line number Diff line
@@ -16,12 +16,14 @@

#include "test_environment.h"

#include <type_traits>  // for remove_extent_t
#include <utility>      // for move
#include <vector>       // for vector
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

#include "net/async_data_channel.h"  // for AsyncDataChannel
#include "os/log.h"                  // for LOG_INFO, LOG_ERROR, LOG_WARN
#include "os/log.h"

namespace android {
namespace bluetooth {
@@ -50,16 +52,13 @@ void TestEnvironment::initialize(std::promise<void> barrier) {
      });

  SetUpTestChannel();
  SetUpHciServer([this](std::shared_ptr<AsyncDataChannel> socket,
                        AsyncDataChannelServer* srv) {
    test_model_.IncomingHciConnection(socket);
    srv->StartListening();
  });
  SetUpLinkLayerServer([this](std::shared_ptr<AsyncDataChannel> socket,
                              AsyncDataChannelServer* srv) {
    test_model_.IncomingLinkLayerConnection(socket);
    srv->StartListening();
  });
  SetUpHciServer([this](int fd) { test_model_.IncomingHciConnection(fd); });
  SetUpLinkLayerServer([this](int fd) { test_model_.IncomingLinkLayerConnection(fd); });

  // In case the client socket is closed, and rootcanal doesn't detect it due to
  // TimerTick not fired, writing to the socket causes a SIGPIPE and we need to
  // catch it to prevent rootcanal from crash
  signal(SIGPIPE, SIG_IGN);

  LOG_INFO("%s: Finished", __func__);
}
@@ -69,54 +68,92 @@ void TestEnvironment::close() {
  test_model_.Reset();
}

void TestEnvironment::SetUpHciServer(ConnectCallback connection_callback) {
  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No HCI Response channel: %s", response.c_str());
  });
void TestEnvironment::SetUpHciServer(const std::function<void(int)>& connection_callback) {
  int socket_fd = remote_hci_transport_.SetUp(hci_server_port_);

  test_channel_.RegisterSendResponse(
      [](const std::string& response) { LOG_INFO("No HCI Response channel: %s", response.c_str()); });

  if (!remote_hci_transport_.SetUp(hci_socket_server_, connection_callback)) {
    LOG_ERROR("Remote HCI channel SetUp failed.");
  if (socket_fd == -1) {
    LOG_ERROR("Remote HCI channel SetUp(%d) failed.", hci_server_port_);
    return;
  }
}

void TestEnvironment::SetUpLinkLayerServer(
    ConnectCallback connection_callback) {
  remote_link_layer_transport_.SetUp(link_socket_server_, connection_callback);
  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
    int conn_fd = remote_hci_transport_.Accept(socket_fd);
    if (conn_fd < 0) {
      LOG_ERROR("Error watching remote HCI channel fd.");
      return;
    }
    int flags = fcntl(conn_fd, F_GETFL, NULL);
    int ret;
    ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
    ASSERT_LOG(ret != -1, "Error setting O_NONBLOCK %s", strerror(errno));

  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No LinkLayer Response channel: %s", response.c_str());
    connection_callback(conn_fd);
  });
}

std::shared_ptr<AsyncDataChannel> TestEnvironment::ConnectToRemoteServer(
    const std::string& server, int port) {
  return connector_->ConnectToRemoteServer(server, port);
void TestEnvironment::SetUpLinkLayerServer(const std::function<void(int)>& connection_callback) {
  int socket_fd = remote_link_layer_transport_.SetUp(link_server_port_);

  test_channel_.RegisterSendResponse(
      [](const std::string& response) { LOG_INFO("No LinkLayer Response channel: %s", response.c_str()); });

  if (socket_fd == -1) {
    LOG_ERROR("Remote LinkLayer channel SetUp(%d) failed.", link_server_port_);
    return;
  }

void TestEnvironment::SetUpTestChannel() {
  bool transport_configured = test_channel_transport_.SetUp(
      test_socket_server_, [this](std::shared_ptr<AsyncDataChannel> conn_fd,
                                  AsyncDataChannelServer*) {
        LOG_INFO("Test channel connection accepted.");
        if (test_channel_open_) {
          LOG_WARN("Only one connection at a time is supported");
          test_channel_transport_.SendResponse(conn_fd,
                                               "The connection is broken");
          return false;
  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
    int conn_fd = remote_link_layer_transport_.Accept(socket_fd);
    if (conn_fd < 0) {
      LOG_ERROR("Error watching remote LinkLayer channel fd.");
      return;
    }
        test_channel_open_ = true;
        test_channel_.RegisterSendResponse(
            [this, conn_fd](const std::string& response) {
              test_channel_transport_.SendResponse(conn_fd, response);
            });
    int flags = fcntl(conn_fd, F_GETFL, NULL);
    int ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
    ASSERT_LOG(ret != -1, "Error setting O_NONBLOCK %s", strerror(errno));

        conn_fd->WatchForNonBlockingRead([this](AsyncDataChannel* conn_fd) {
          test_channel_transport_.OnCommandReady(
              conn_fd, [this]() { test_channel_open_ = false; });
        });
        return false;
    connection_callback(conn_fd);
  });
}

int TestEnvironment::ConnectToRemoteServer(const std::string& server, int port) {
  int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
  if (socket_fd < 1) {
    LOG_INFO("socket() call failed: %s", strerror(errno));
    return -1;
  }

  struct hostent* host;
  host = gethostbyname(server.c_str());
  if (host == NULL) {
    LOG_INFO("gethostbyname() failed for %s: %s", server.c_str(), strerror(errno));
    return -1;
  }

  struct sockaddr_in serv_addr {};
  memset((void*)&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(port);

  int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
  if (result < 0) {
    LOG_INFO("connect() failed for %s@%d: %s", server.c_str(), port, strerror(errno));
    return -1;
  }

  int flags = fcntl(socket_fd, F_GETFL, NULL);
  int ret = fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK);
  ASSERT_LOG(ret != -1, "Error setting O_NONBLOCK %s", strerror(errno));

  return socket_fd;
}

void TestEnvironment::SetUpTestChannel() {
  int socket_fd = test_channel_transport_.SetUp(test_port_);
  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No test channel: %s", response.c_str());
  });
@@ -127,12 +164,39 @@ void TestEnvironment::SetUpTestChannel() {

  test_channel_.FromFile(default_commands_file_);

  if (!transport_configured) {
    LOG_ERROR("Test channel SetUp failed.");
  if (socket_fd == -1) {
    LOG_ERROR("Test channel SetUp(%d) failed.", test_port_);
    return;
  }

  LOG_INFO("Test channel SetUp() successful");
  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this](int socket_fd) {
    int conn_fd = test_channel_transport_.Accept(socket_fd);
    if (conn_fd < 0) {
      LOG_ERROR("Error watching test channel fd.");
      barrier_.set_value();
      return;
    }
    LOG_INFO("Test channel connection accepted.");
    if (test_channel_open_) {
      LOG_WARN("Only one connection at a time is supported");
      async_manager_.StopWatchingFileDescriptor(conn_fd);
      test_channel_transport_.SendResponse(conn_fd, "The connection is broken");
      return;
    }
    test_channel_open_ = true;
    test_channel_.RegisterSendResponse(
        [this, conn_fd](const std::string& response) {
          test_channel_transport_.SendResponse(conn_fd, response);
        });

    async_manager_.WatchFdForNonBlockingReads(conn_fd, [this](int conn_fd) {
      test_channel_transport_.OnCommandReady(conn_fd, [this, conn_fd]() {
        async_manager_.StopWatchingFileDescriptor(conn_fd);
        test_channel_open_ = false;
      });
    });
  });
}

}  // namespace root_canal
+20 −39
Original line number Diff line number Diff line
@@ -16,45 +16,27 @@

#pragma once

#include <chrono>      // for milliseconds
#include <functional>  // for __base, function
#include <future>      // for promise
#include <memory>      // for shared_ptr, make_...
#include <string>      // for string

#include "model/controller/dual_mode_controller.h"  // for DualModeController
#include "model/setup/async_manager.h"              // for AsyncTaskId, Asyn...
#include "model/setup/test_channel_transport.h"     // for TestChannelTransport
#include "model/setup/test_command_handler.h"       // for TestCommandHandler
#include "model/setup/test_model.h"                 // for TestModel
#include "net/async_data_channel_server.h"          // for AsyncDataChannelS...
#include <future>

namespace android {
namespace net {
class AsyncDataChannel;
class AsyncDataChannelConnector;
}  // namespace net
#include "model/controller/dual_mode_controller.h"
#include "model/setup/async_manager.h"
#include "model/setup/test_channel_transport.h"
#include "model/setup/test_command_handler.h"
#include "model/setup/test_model.h"

namespace android {
namespace bluetooth {
namespace root_canal {

using android::net::AsyncDataChannel;
using android::net::AsyncDataChannelConnector;
using android::net::AsyncDataChannelServer;
using android::net::ConnectCallback;

class TestEnvironment {
 public:
  TestEnvironment(std::shared_ptr<AsyncDataChannelServer> test_port,
                  std::shared_ptr<AsyncDataChannelServer> hci_server_port,
                  std::shared_ptr<AsyncDataChannelServer> link_server_port,
                  std::shared_ptr<AsyncDataChannelConnector> connector,
  TestEnvironment(uint16_t test_port, uint16_t hci_server_port,
                  uint16_t link_server_port,
                  const std::string& controller_properties_file = "",
                  const std::string& default_commands_file = "")
      : test_socket_server_(test_port),
        hci_socket_server_(hci_server_port),
        link_socket_server_(link_server_port),
        connector_(connector),
      : test_port_(test_port),
        hci_server_port_(hci_server_port),
        link_server_port_(link_server_port),
        default_commands_file_(default_commands_file),
        controller_(std::make_shared<test_vendor_lib::DualModeController>(
            controller_properties_file)) {}
@@ -64,10 +46,9 @@ class TestEnvironment {
  void close();

 private:
  std::shared_ptr<AsyncDataChannelServer> test_socket_server_;
  std::shared_ptr<AsyncDataChannelServer> hci_socket_server_;
  std::shared_ptr<AsyncDataChannelServer> link_socket_server_;
  std::shared_ptr<AsyncDataChannelConnector> connector_;
  uint16_t test_port_;
  uint16_t hci_server_port_;
  uint16_t link_server_port_;
  std::string default_commands_file_;
  bool test_channel_open_{false};
  std::promise<void> barrier_;
@@ -75,10 +56,9 @@ class TestEnvironment {
  test_vendor_lib::AsyncManager async_manager_;

  void SetUpTestChannel();
  void SetUpHciServer(ConnectCallback on_connect);
  void SetUpLinkLayerServer(ConnectCallback on_connect);
  std::shared_ptr<AsyncDataChannel> ConnectToRemoteServer(
      const std::string& server, int port);
  void SetUpHciServer(const std::function<void(int)>& on_connect);
  void SetUpLinkLayerServer(const std::function<void(int)>& on_connect);
  int ConnectToRemoteServer(const std::string& server, int port);

  std::shared_ptr<test_vendor_lib::DualModeController> controller_;

@@ -115,6 +95,7 @@ class TestEnvironment {

  test_vendor_lib::TestCommandHandler test_channel_{test_model_};
};

}  // namespace root_canal
}  // namespace bluetooth
}  // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ size_t H4DataChannelPacketizer::Send(uint8_t type, const uint8_t* data,

void H4DataChannelPacketizer::OnDataReady(
    std::shared_ptr<AsyncDataChannel> socket) {
  if (!socket->Connected()) return;
  ssize_t bytes_to_read = h4_parser_.BytesRequested();
  std::vector<uint8_t> buffer(bytes_to_read);

Loading