From 71f54ac820eb6ffe65d18e35eaacced38c591b12 Mon Sep 17 00:00:00 2001 From: Vibhav Pant Date: Tue, 26 Sep 2023 18:35:48 +0530 Subject: [PATCH] Add headers. --- .../implementation/linux/bluez_device.h | 65 +++++++ .../implementation/linux/tcp_server_socket.h | 173 ++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 internal/platform/implementation/linux/bluez_device.h create mode 100644 internal/platform/implementation/linux/tcp_server_socket.h diff --git a/internal/platform/implementation/linux/bluez_device.h b/internal/platform/implementation/linux/bluez_device.h new file mode 100644 index 00000000..f419cbf0 --- /dev/null +++ b/internal/platform/implementation/linux/bluez_device.h @@ -0,0 +1,65 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PLATFORM_IMPL_LINUX_BLUEZ_DEVICE_H_ +#define PLATFORM_IMPL_LINUX_BLUEZ_DEVICE_H_ +#include +#include +#include + +#include "absl/functional/any_invocable.h" +#include "absl/synchronization/mutex.h" +#include "internal/platform/implementation/linux/generated/dbus/bluez/device_client.h" + +namespace nearby { +namespace linux { +namespace bluez { +class Device : public sdbus::ProxyInterfaces { + public: + Device(std::shared_ptr system_bus, + const sdbus::ObjectPath &device_path) + : ProxyInterfaces(*system_bus, "org.bluez", device_path), + system_bus(std::move(system_bus)) { + registerProxy(); + } + ~Device() { unregisterProxy(); } + + void SetPairReplyCallback(absl::AnyInvocable cb) + ABSL_LOCKS_EXCLUDED(pair_callback_lock_) { + absl::MutexLock l(&pair_callback_lock_); + on_pair_reply_cb_ = std::move(cb); + } + + void ResetPairReplyCallback() ABSL_LOCKS_EXCLUDED(pair_callback_lock_) { + absl::MutexLock l(&pair_callback_lock_); + on_pair_reply_cb_ = nullptr; + } + + protected: + void onPairReply(const sdbus::Error *error) override + ABSL_LOCKS_EXCLUDED(pair_callback_lock_) { + absl::ReaderMutexLock l(&pair_callback_lock_); + if (on_pair_reply_cb_ != nullptr) on_pair_reply_cb_(error); + }; + + private: + std::shared_ptr system_bus; + absl::Mutex pair_callback_lock_; + absl::AnyInvocable on_pair_reply_cb_ + ABSL_GUARDED_BY(pair_callback_lock_) = nullptr; +}; +} // namespace bluez +} // namespace linux +} // namespace nearby +#endif diff --git a/internal/platform/implementation/linux/tcp_server_socket.h b/internal/platform/implementation/linux/tcp_server_socket.h new file mode 100644 index 00000000..764360c9 --- /dev/null +++ b/internal/platform/implementation/linux/tcp_server_socket.h @@ -0,0 +1,173 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PLATFORM_IMPL_LINUX_TCP_SERVER_SOCKET_H_ +#define PLATFORM_IMPL_LINUX_TCP_SERVER_SOCKET_H_ + +#include +#include +#include +#include + +#include + +#include "internal/platform/exception.h" +#include "internal/platform/implementation/linux/stream.h" +#include "internal/platform/logging.h" + +namespace nearby { +namespace linux { +class TCPSocket { + public: + explicit TCPSocket(const sdbus::UnixFd& fd) + : closed_(false), output_stream_(fd), input_stream_(fd) {} + + static std::optional Connect(const std::string& ip_address, + int port) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error opening socket: " << std::strerror(errno); + return std::nullopt; + } + + NEARBY_LOGS(VERBOSE) << __func__ << ": Connecting to " << ip_address << ":" + << port; + struct sockaddr_in addr; + addr.sin_addr.s_addr = inet_addr(ip_address.c_str()); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + auto ret = + connect(sock, reinterpret_cast(&addr), sizeof(addr)); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error connecting to socket: " + << std::strerror(errno); + return std::nullopt; + } + + return TCPSocket(sdbus::UnixFd(sock)); + } + + InputStream& GetInputStream() { return input_stream_; } + OutputStream& GetOutputStream() { return output_stream_; } + + Exception Close() { + if (closed_) return {Exception::kFailed}; + + closed_ = true; + input_stream_.Close(); + output_stream_.Close(); + + return {Exception::kSuccess}; + }; + + private: + bool closed_; + + OutputStream output_stream_; + InputStream input_stream_; +}; + +class TCPServerSocket { + public: + explicit TCPServerSocket(int fd) : fd_(fd) {} + + static std::optional Listen( + std::optional> ip_address, + int port) { + auto sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error opening socket: " << std::strerror(errno); + return std::nullopt; + } + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + if (ip_address.has_value()) + addr.sin_addr.s_addr = inet_addr(ip_address->get().c_str()); + else + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + auto ret = + bind(sock, reinterpret_cast(&addr), sizeof(addr)); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error binding to socket: " + << std::strerror(errno); + return std::nullopt; + } + + ret = listen(sock, 0); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error listening on socket: " + << std::strerror(errno); + return std::nullopt; + } + + return TCPServerSocket(sock); + } + std::optional Accept() { + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + + auto conn = + accept(fd_.get(), reinterpret_cast(&addr), &len); + if (conn < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error accepting incoming connections on socket " + << fd_.get() << ": " << std::strerror(errno); + return std::nullopt; + } + + return TCPSocket(sdbus::UnixFd(conn)); + }; + + Exception Close() { + int fd = fd_.release(); + shutdown(fd, SHUT_RDWR); + auto ret = close(fd); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error closing socket " << fd << ": " + << std::strerror(errno); + return {Exception::kFailed}; + } + + return {Exception::kSuccess}; + }; + + int GetPort() const { + struct sockaddr_in sin; + socklen_t len = sizeof(sin); + auto ret = + getsockname(fd_.get(), reinterpret_cast(&sin), &len); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error getting information for socket " + << fd_.get() << ": " << std::strerror(errno); + return 0; + } + + return ntohs(sin.sin_port); + } + + private: + sdbus::UnixFd fd_; +}; +} // namespace linux +} // namespace nearby + +#endif