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

Commit c0d824f0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Use abstract datachannels in Root Canal."

parents 05332200 a3ae33f0
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ 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",
+16 −10
Original line number Diff line number Diff line
@@ -13,21 +13,24 @@
// 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 "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");
@@ -111,10 +114,13 @@ int main(int argc, char** argv) {
      }
    }
  }

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

#include "test_environment.h"

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

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

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

  SetUpTestChannel();
  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);
  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();
  });

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

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 (socket_fd == -1) {
    LOG_ERROR("Remote HCI channel SetUp(%d) failed.", hci_server_port_);
    return;
  }

  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));

    connection_callback(conn_fd);
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::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_);
  if (!remote_hci_transport_.SetUp(hci_socket_server_, connection_callback)) {
    LOG_ERROR("Remote HCI channel SetUp failed.");
    return;
  }

  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;
    }
    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));

    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;
  }
void TestEnvironment::SetUpLinkLayerServer(
    ConnectCallback connection_callback) {
  remote_link_layer_transport_.SetUp(link_socket_server_, connection_callback);

  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;
  test_channel_.RegisterSendResponse([](const std::string& response) {
    LOG_INFO("No LinkLayer Response channel: %s", response.c_str());
  });
}

  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;
std::shared_ptr<AsyncDataChannel> TestEnvironment::ConnectToRemoteServer(
    const std::string& server, int port) {
  return connector_->ConnectToRemoteServer(server, port);
}

  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() {
  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;
        }
        test_channel_open_ = true;
        test_channel_.RegisterSendResponse(
            [this, conn_fd](const std::string& response) {
              test_channel_transport_.SendResponse(conn_fd, response);
            });

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

  test_channel_.FromFile(default_commands_file_);

  if (socket_fd == -1) {
    LOG_ERROR("Test channel SetUp(%d) failed.", test_port_);
  if (!transport_configured) {
    LOG_ERROR("Test channel SetUp failed.");
    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
+39 −20
Original line number Diff line number Diff line
@@ -16,27 +16,45 @@

#pragma once

#include <future>

#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"
#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...

namespace android {
namespace net {
class AsyncDataChannel;
class AsyncDataChannelConnector;
}  // namespace net

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

 private:
  uint16_t test_port_;
  uint16_t hci_server_port_;
  uint16_t link_server_port_;
  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_;
  std::string default_commands_file_;
  bool test_channel_open_{false};
  std::promise<void> barrier_;
@@ -56,9 +75,10 @@ class TestEnvironment {
  test_vendor_lib::AsyncManager async_manager_;

  void SetUpTestChannel();
  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);
  void SetUpHciServer(ConnectCallback on_connect);
  void SetUpLinkLayerServer(ConnectCallback on_connect);
  std::shared_ptr<AsyncDataChannel> ConnectToRemoteServer(
      const std::string& server, int port);

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

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

  test_vendor_lib::TestCommandHandler test_channel_{test_model_};
};

}  // namespace root_canal
}  // namespace bluetooth
}  // namespace android
 No newline at end of file
+0 −1
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ 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