From d7f703a991aa830eaaf535e87dae245d8492e096 Mon Sep 17 00:00:00 2001 From: lasan Date: Thu, 11 Jun 2026 13:04:11 +0530 Subject: [PATCH] Reapply "removed bluetooth_classic_socket specific stream semantics. all linux sockets should use stream.h. improved stream semantics in stream.h" This reverts commit 844bf42e7ef3fc6bc6207e8a9b13e99d455703f1. --- MODULE.bazel | 12 ++ MODULE.bazel.lock | 183 +----------------- internal/platform/implementation/linux/BUILD | 38 ++-- .../implementation/linux/ble_l2cap_socket.cc | 49 ++--- .../implementation/linux/ble_l2cap_socket.h | 2 + .../linux/bluetooth_classic_socket.cc | 126 ------------ .../linux/bluetooth_classic_socket.h | 41 +--- .../platform/implementation/linux/stream.cc | 153 ++++++++++++--- .../platform/implementation/linux/stream.h | 8 +- .../implementation/linux/timer_test.cc | 29 +-- sharing/linux/BUILD | 17 ++ 11 files changed, 232 insertions(+), 426 deletions(-) delete mode 100644 internal/platform/implementation/linux/bluetooth_classic_socket.cc diff --git a/MODULE.bazel b/MODULE.bazel index 33450200..a465e98b 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -122,6 +122,18 @@ filegroup( ], ) +# Bazel Compile Commands Extractor (helly25 fork; see FORK.md for context) +# https://github.com/helly25/bazel-compile-commands-extractor +bazel_dep(name = "hedron_compile_commands", dev_dependency = True) # Bazel module name kept for backwards compat with existing consumers. +git_override( + module_name = "hedron_compile_commands", + remote = "https://github.com/helly25/bazel-compile-commands-extractor.git", + commit = "75ba4c31d3b74fa5fb57c7508220571d4e52f828", + # Replace the commit hash with the latest from + # https://github.com/helly25/bazel-compile-commands-extractor/commits/main + # (or set up Renovate; see below). +) + # Create a repo that exposes system-installed sdbus-c++ and libsystemd to Bazel. # # Important portability note: diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 348ddaef..a4169fee 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -40,7 +40,8 @@ "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6", "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080", - "https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309", + "https://bcr.bazel.build/modules/bazel_features/1.43.0/MODULE.bazel": "defa2226f06ba20550d6548c3a2ea2a7929634437a52973869c20c225450eb91", + "https://bcr.bazel.build/modules/bazel_features/1.43.0/source.json": "1c4207dc858d6de0eecef30026793616bbf420c74aac27b6bad212534a730437", "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", @@ -53,6 +54,7 @@ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.0/MODULE.bazel": "2fb3fb53675f6adfc1ca5bfbd5cfb655ae350fba4706d924a8ec7e3ba945671c", "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", "https://bcr.bazel.build/modules/bazel_skylib/1.9.0/MODULE.bazel": "72997b29dfd95c3fa0d0c48322d05590418edef451f8db8db5509c57875fb4b7", @@ -130,7 +132,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8", "https://bcr.bazel.build/modules/rules_cc/0.2.16/MODULE.bazel": "9242fa89f950c6ef7702801ab53922e99c69b02310c39fb6e62b2bd30df2a1d4", "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", - "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", + "https://bcr.bazel.build/modules/rules_cc/0.2.18/MODULE.bazel": "4460ec36adc8f722a6a2a4ac9374cb91f2acebadaa93fc37966129afb3dece87", + "https://bcr.bazel.build/modules/rules_cc/0.2.18/source.json": "abad668ff2fd63ada1ac49bf386d37e27048b89a3465a6fd968bb832b00a09d3", "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", "https://bcr.bazel.build/modules/rules_cc/0.2.9/MODULE.bazel": "34263f1dca62ea664265438cef714d7db124c03e1ed55ebb4f1dc860164308d1", @@ -186,7 +189,8 @@ "https://bcr.bazel.build/modules/rules_python/1.5.1/MODULE.bazel": "acfe65880942d44a69129d4c5c3122d57baaf3edf58ae5a6bd4edea114906bf5", "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8", "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8", - "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32", + "https://bcr.bazel.build/modules/rules_python/2.0.1/MODULE.bazel": "294fbfe4dc3b24a925172e5487e1e8d3c2927cf4fba1eaddd7bad0ce50701da1", + "https://bcr.bazel.build/modules/rules_python/2.0.1/source.json": "f2bacc75d3fc496dfd3e6a5986200b10e70169aaaf4ee5f1cea573c8d347e7c4", "https://bcr.bazel.build/modules/rules_rust/0.68.1/MODULE.bazel": "8d3332ef4079673385eb81f8bd68b012decc04ac00c9d5a01a40eff90301732c", "https://bcr.bazel.build/modules/rules_rust/0.68.1/source.json": "3378e746f81b62457fdfd37391244fa8ff075ba85c05931ee4f3a20ac1efe963", "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", @@ -202,7 +206,6 @@ "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", - "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f", "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b", @@ -272,178 +275,10 @@ } } }, - "@@rules_python+//python/extensions:config.bzl%config": { - "general": { - "bzlTransitiveDigest": "iibnRYgg8LpcfmH7EAnVwYePC3jsVaJ6Id8XxUjSZps=", - "usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=", - "recordedInputs": [ - "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", - "REPO_MAPPING:rules_python+,pypi__build rules_python++config+pypi__build", - "REPO_MAPPING:rules_python+,pypi__click rules_python++config+pypi__click", - "REPO_MAPPING:rules_python+,pypi__colorama rules_python++config+pypi__colorama", - "REPO_MAPPING:rules_python+,pypi__importlib_metadata rules_python++config+pypi__importlib_metadata", - "REPO_MAPPING:rules_python+,pypi__installer rules_python++config+pypi__installer", - "REPO_MAPPING:rules_python+,pypi__more_itertools rules_python++config+pypi__more_itertools", - "REPO_MAPPING:rules_python+,pypi__packaging rules_python++config+pypi__packaging", - "REPO_MAPPING:rules_python+,pypi__pep517 rules_python++config+pypi__pep517", - "REPO_MAPPING:rules_python+,pypi__pip rules_python++config+pypi__pip", - "REPO_MAPPING:rules_python+,pypi__pip_tools rules_python++config+pypi__pip_tools", - "REPO_MAPPING:rules_python+,pypi__pyproject_hooks rules_python++config+pypi__pyproject_hooks", - "REPO_MAPPING:rules_python+,pypi__setuptools rules_python++config+pypi__setuptools", - "REPO_MAPPING:rules_python+,pypi__tomli rules_python++config+pypi__tomli", - "REPO_MAPPING:rules_python+,pypi__wheel rules_python++config+pypi__wheel", - "REPO_MAPPING:rules_python+,pypi__zipp rules_python++config+pypi__zipp" - ], - "generatedRepoSpecs": { - "rules_python_internal": { - "repoRuleId": "@@rules_python+//python/private:internal_config_repo.bzl%internal_config_repo", - "attributes": { - "transition_setting_generators": {}, - "transition_settings": [] - } - }, - "pypi__build": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/e2/03/f3c8ba0a6b6e30d7d18c40faab90807c9bb5e9a1e3b2fe2008af624a9c97/build-1.2.1-py3-none-any.whl", - "sha256": "75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__click": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", - "sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__colorama": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", - "sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__importlib_metadata": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl", - "sha256": "30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__installer": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl", - "sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__more_itertools": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/50/e2/8e10e465ee3987bb7c9ab69efb91d867d93959095f4807db102d07995d94/more_itertools-10.2.0-py3-none-any.whl", - "sha256": "686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__packaging": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", - "sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__pep517": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/25/6e/ca4a5434eb0e502210f591b97537d322546e4833dcb4d470a48c375c5540/pep517-0.13.1-py3-none-any.whl", - "sha256": "31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__pip": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl", - "sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__pip_tools": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl", - "sha256": "4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__pyproject_hooks": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/ae/f3/431b9d5fe7d14af7a32340792ef43b8a714e7726f1d7b69cc4e8e7a3f1d7/pyproject_hooks-1.1.0-py3-none-any.whl", - "sha256": "7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__setuptools": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl", - "sha256": "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__tomli": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", - "sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__wheel": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl", - "sha256": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__zipp": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/da/55/a03fd7240714916507e1fcf7ae355bd9d9ed2e6db492595f1a67f61681be/zipp-3.18.2-py3-none-any.whl", - "sha256": "dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - } - } - } - }, "@@rules_python+//python/uv:uv.bzl%uv": { "general": { - "bzlTransitiveDigest": "ijW9KS7qsIY+yBVvJ+Nr1mzwQox09j13DnE3iIwaeTM=", - "usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=", + "bzlTransitiveDigest": "I8FPZMevE2oI/peSpMBRVIN++WOtfjtJVjbPsBZQ87A=", + "usagesDigest": "KI88AZslgI1K52IZ7PfBqhuXb5hke0gUD9N73XeVqaI=", "recordedInputs": [ "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", "REPO_MAPPING:rules_python+,platforms platforms" diff --git a/internal/platform/implementation/linux/BUILD b/internal/platform/implementation/linux/BUILD index 8ee54236..ad1b127e 100644 --- a/internal/platform/implementation/linux/BUILD +++ b/internal/platform/implementation/linux/BUILD @@ -12,25 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. -#load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands") - +load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands") load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -#refresh_compile_commands( -# name = "refresh_compile_commands", -# -# # Specify the targets of interest. -# # For example, specify a dict of targets and any flags required to build. -# targets = { -# ":linux": "-s --check_visibility=false --spawn_strategy=standalone --verbose_failures --strip=never --copt=-O0 --copt=-g --copt=-fno-omit-frame-pointer", -# "//connections:core": "-s --check_visibility=false --spawn_strategy=standalone --verbose_failures --strip=never --copt=-O0 --copt=-g --copt=-fno-omit-frame-pointer", -# "//connections/file_share:file_share": "-s --check_visibility=false --spawn_strategy=standalone --verbose_failures --strip=never --copt=-O0 --copt=-g --copt=-fno-omit-frame-pointer", -# }, -# # No need to add flags already in .bazelrc. They're automatically picked up. -# # If you don't need flags, a list of targets is also okay, as is a single target string. -# # Wildcard patterns, like //... for everything, *are* allowed here, just like a build. -# # As are additional targets (+) and subtractions (-), like in bazel query https://docs.bazel.build/versions/main/query.html#expressions -# # And if you're working on a header-only library, specify a test or binary target that compiles it. -#) + +refresh_compile_commands( + name = "refresh_compile_commands_linux", + + # Specify the targets of interest. + # For example, specify a dict of targets and any flags required to build. + targets = { + ":linux": "-s --check_visibility=false --spawn_strategy=standalone --verbose_failures --cxxopt=-std=c++20 --host_cxxopt=-std=c++20 --cxxopt='-fvisibility-inlines-hidden'", + }, + # No need to add flags already in .bazelrc. They're automatically picked up. + # If you don't need flags, a list of targets is also okay, as is a single target string. + # Wildcard patterns, like //... for everything, *are* allowed here, just like a build. + # As are additional targets (+) and subtractions (-), like in bazel query https://docs.bazel.build/versions/main/query.html#expressions + # And if you're working on a header-only library, specify a test or binary target that compiles it. +) + licenses(["notice"]) @@ -200,7 +199,6 @@ cc_library( "ble_l2cap_socket.cc", "bluetooth_adapter.cc", "bluetooth_bluez_profile.cc", - "bluetooth_classic_socket.cc", "bluetooth_classic_device.cc", "bluetooth_classic_medium.cc", "bluetooth_classic_server_socket.cc", @@ -314,7 +312,7 @@ cc_test( # "bluetooth_adapter_test.cc", "crypto_test.cc", # "executor_test.cc", - "file_path_test.cc", + # "file_path_test.cc", # "http_loader_test.cc", # "preferences_manager_test.cc", # "preferences_repository_test.cc", diff --git a/internal/platform/implementation/linux/ble_l2cap_socket.cc b/internal/platform/implementation/linux/ble_l2cap_socket.cc index e8f26c0c..a12ad0a7 100644 --- a/internal/platform/implementation/linux/ble_l2cap_socket.cc +++ b/internal/platform/implementation/linux/ble_l2cap_socket.cc @@ -34,7 +34,9 @@ namespace nearby { namespace linux { -BleL2capInputStream::~BleL2capInputStream() { Close(); } +BleL2capInputStream::~BleL2capInputStream() { + Close(); +} ExceptionOr BleL2capInputStream::Read(std::int64_t size) { std::vector buffer(size); @@ -54,22 +56,24 @@ ExceptionOr BleL2capInputStream::Read(std::int64_t size) { } if (pfds[0].revents & POLLIN) { auto r = recv(fd_raw_->get(), buffer.data() + rcvd, size - rcvd, 0); - if (r < 0){ return Exception{Exception::kIo};} + if (r < 0) { + return Exception{Exception::kIo}; + } rcvd += r; } } - return ExceptionOr{ByteArray(std::string(buffer.begin(), buffer.end()))}; } Exception BleL2capInputStream::Close() { if (!fd_raw_->isValid()) return {Exception::kSuccess}; - fd_raw_ -> reset(); - return {Exception::kSuccess}; - + fd_raw_->reset(); + return {Exception::kSuccess}; +} +BleL2capOutputStream::~BleL2capOutputStream() { + Close(); } -BleL2capOutputStream::~BleL2capOutputStream() { Close(); } Exception BleL2capOutputStream::Write(absl::string_view data) { pollfd pfds[1]; @@ -87,7 +91,9 @@ Exception BleL2capOutputStream::Write(absl::string_view data) { } if (pfds[0].revents & POLLOUT) { auto r = send(fd_raw_->get(), data.data() + sent, data.size(), 0); - if (r < 0){ return Exception{Exception::kIo};} + if (r < 0) { + return Exception{Exception::kIo}; + } sent += r; } } @@ -96,32 +102,29 @@ Exception BleL2capOutputStream::Write(absl::string_view data) { Exception BleL2capOutputStream::Close() { if (!fd_raw_->isValid()) return {Exception::kSuccess}; - fd_raw_ -> reset(); - return {Exception::kSuccess}; + fd_raw_->reset(); + return {Exception::kSuccess}; } BleL2capSocket::BleL2capSocket(int fd, api::ble::BlePeripheral::UniqueId peripheral_id, - std::string service_id - ) - : fd_(std::make_shared(fd)), input_stream_(std::make_unique(fd_)), + std::string service_id) + : fd_(std::make_shared(fd)), + input_stream_(std::make_unique(fd_)), output_stream_(std::make_unique(fd_)), - peripheral_id_(peripheral_id) - {} - -BleL2capSocket::~BleL2capSocket() { Close(); } - + peripheral_id_(peripheral_id) {} +BleL2capSocket::~BleL2capSocket() { + Close(); +} Exception BleL2capSocket::Close() { if (!fd_->isValid()) return {Exception::kIo}; - fd_ -> reset(); - return {Exception::kSuccess}; + fd_->reset(); + return {Exception::kSuccess}; } - -void BleL2capSocket::SetCloseNotifier(absl::AnyInvocable notifier) { -} +void BleL2capSocket::SetCloseNotifier(absl::AnyInvocable notifier) {} bool BleL2capSocket::IsClosed() const { return closed_; diff --git a/internal/platform/implementation/linux/ble_l2cap_socket.h b/internal/platform/implementation/linux/ble_l2cap_socket.h index cdea0bf1..d13ba98c 100644 --- a/internal/platform/implementation/linux/ble_l2cap_socket.h +++ b/internal/platform/implementation/linux/ble_l2cap_socket.h @@ -35,6 +35,8 @@ namespace nearby { namespace linux { +// TODO: use linux stream instead of bespoke l2cap input/output stream + class BleL2capSocket; class BleL2capInputStream final : public InputStream { diff --git a/internal/platform/implementation/linux/bluetooth_classic_socket.cc b/internal/platform/implementation/linux/bluetooth_classic_socket.cc deleted file mode 100644 index f1ff28f7..00000000 --- a/internal/platform/implementation/linux/bluetooth_classic_socket.cc +++ /dev/null @@ -1,126 +0,0 @@ -// 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. - -#include -#include -#include -#include -#include -#include -#include - -#include "internal/platform/byte_array.h" -#include "internal/platform/exception.h" -#include "internal/platform/implementation/linux/bluetooth_classic_socket.h" -#include "internal/platform/logging.h" - -#include -#include -#include -#include -#include - -namespace nearby { -namespace linux { - -// This method blocks until input data is available, end of file is detected, or an exception is thrown. -ExceptionOr BluetoothInputStream::Read(std::int64_t size) { - // Sanity: avoid negative / zero sizes - if (size <= 0) return ExceptionOr{ByteArray(std::string())}; - - - std::vector buffer(size); - - // fd returned from bluez assumed to be stream type always - - pollfd pfds[1]; - pfds[0].fd = fd_raw_->get(); - pfds[0].events = POLLIN; - ssize_t rcvd = 0; - - while (rcvd < size) { - int r = poll(pfds, 1, -1); - if (r < 0) { - if (errno == EINTR) { - continue; - } - return Exception{Exception::kIo}; - } - if (pfds[0].revents & POLLIN) { - while (rcvd < size) { - - auto r = recv(fd_raw_->get(), buffer.data() + rcvd, size - rcvd, 0); - if (r > 0) { - rcvd += r; - continue; - } - if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {continue;} - - LOG(ERROR) << __func__ - << ": error reading from fd: " << std::strerror(errno); - return {Exception::kIo}; - } - } - } - - - return ExceptionOr{ByteArray(std::string(buffer.begin(), buffer.end()))}; -} - -Exception BluetoothInputStream::Close() { - if (!fd_raw_->isValid()) return {Exception::kSuccess}; - fd_raw_ -> reset(); - return {Exception::kSuccess}; -} - -Exception BluetoothOutputStream::Write(absl::string_view data) { - pollfd pfds[1]; - pfds[0].fd = fd_raw_->get(); - pfds[0].events = POLLOUT; - ssize_t sent = 0; - - while (sent < data.size()) { - int r = poll(pfds, 1, -1); - if (r < 0) { - if (errno == EINTR) { - continue; - } - return Exception{Exception::kIo}; - } - if (pfds[0].revents & POLLOUT) { - while (sent < data.size()) { - auto r = send(fd_raw_->get(), data.data() + sent, data.size(), 0); - if (r > 0) { - sent += r; - continue; - } - if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {continue;} - - LOG(ERROR) << __func__ - << ": error reading from fd: " << std::strerror(errno); - return {Exception::kIo}; - } - } - } - return {Exception::kSuccess}; -} - -Exception BluetoothOutputStream::Close() { - if (!fd_raw_->isValid()) return {Exception::kSuccess}; - fd_raw_ -> reset(); - return {Exception::kSuccess}; -} - -} // namespace linux -} // namespace nearby diff --git a/internal/platform/implementation/linux/bluetooth_classic_socket.h b/internal/platform/implementation/linux/bluetooth_classic_socket.h index b9fe89e6..a1353713 100644 --- a/internal/platform/implementation/linux/bluetooth_classic_socket.h +++ b/internal/platform/implementation/linux/bluetooth_classic_socket.h @@ -27,46 +27,21 @@ #include "internal/platform/exception.h" #include "internal/platform/implementation/bluetooth_classic.h" #include "internal/platform/implementation/linux/bluetooth_classic_device.h" -#include "internal/platform/input_stream.h" -#include "internal/platform/output_stream.h" + +#include "internal/platform/implementation/linux/stream.h" namespace nearby { namespace linux { -class BluetoothInputStream final : public nearby::InputStream { - public: - explicit BluetoothInputStream(std::shared_ptr fd) - : fd_raw_(std::move(fd)){} - - ExceptionOr Read(std::int64_t size) override; - Exception Close() override; - - private: - std::shared_ptr fd_raw_; -}; - -class BluetoothOutputStream : public nearby::OutputStream { - public: - explicit BluetoothOutputStream(std::shared_ptr fd) - : fd_raw_(std::move(fd)) {} - - Exception Write(absl::string_view data) override; - Exception Flush() override { return {Exception::kSuccess}; } - Exception Close() override; - - private: - mutable absl::Mutex fd_mutex_; - std::shared_ptr fd_raw_; -}; class BluetoothSocket final : public api::BluetoothSocket { public: BluetoothSocket(std::shared_ptr device, sdbus::UnixFd fd) - :fd_(std::make_shared(fd)), device_(std::move(device)), output_stream_(fd_), input_stream_(fd_) {} + :fd_(fd), device_(std::move(device)), output_stream_(fd_), input_stream_(fd_) {} - nearby::InputStream &GetInputStream() override { return input_stream_; } - nearby::OutputStream &GetOutputStream() override { return output_stream_; } + InputStream &GetInputStream() override { return input_stream_; } + OutputStream &GetOutputStream() override { return output_stream_; } Exception Close() override { input_stream_.Close(); output_stream_.Close(); @@ -76,10 +51,10 @@ class BluetoothSocket final : public api::BluetoothSocket { api::BluetoothDevice *GetRemoteDevice() override { return device_.get(); }; private: - std::shared_ptr fd_; + sdbus::UnixFd fd_; std::shared_ptr device_; - BluetoothOutputStream output_stream_; - BluetoothInputStream input_stream_; + OutputStream output_stream_; + InputStream input_stream_; }; } // namespace linux } // namespace nearby diff --git a/internal/platform/implementation/linux/stream.cc b/internal/platform/implementation/linux/stream.cc index 6bfe13e4..bf25e427 100644 --- a/internal/platform/implementation/linux/stream.cc +++ b/internal/platform/implementation/linux/stream.cc @@ -12,8 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include +#include #include #include #include @@ -27,52 +29,149 @@ namespace nearby { namespace linux { ExceptionOr InputStream::Read(std::int64_t size) { - if (!fd_.isValid()) return {Exception::kIo}; + if (size <= 0) { + return ExceptionOr(ByteArray(std::string())); + } + + if (!fd_ || !fd_->isValid()) { + return {Exception::kIo}; + } std::string buffer; buffer.resize(size); - ssize_t ret = recv(fd_.get(), buffer.data(), buffer.size(), MSG_WAITALL); - if (ret == 0) { - return ExceptionOr(ByteArray()); - } - if (ret < 0) { - LOG(ERROR) << __func__ - << ": error reading from fd: " << std::strerror(errno); - return {Exception::kIo}; - } - buffer.resize(ret); - return ExceptionOr(ByteArray(std::move(buffer))); + while (true) { + pollfd pfd{}; + pfd.fd = fd_->get(); + pfd.events = POLLIN; + + int poll_result = poll(&pfd, 1, -1); + + if (poll_result < 0) { + if (errno == EINTR) { + continue; + } + + LOG(ERROR) << __func__ << ": poll failed: " << std::strerror(errno); + return {Exception::kIo}; + } + + if (pfd.revents & POLLNVAL || pfd.revents & POLLERR) { + LOG(ERROR) << __func__ << ": Error reading from BluetoothSocket: " + << std::strerror(errno); + return {Exception::kIo}; + } + + if (pfd.revents & (POLLIN | POLLHUP)) { + ssize_t bytes_read = + recv(fd_->get(), buffer.data(), buffer.size(), 0); + + if (bytes_read > 0) { + buffer.resize(static_cast(bytes_read)); + return ExceptionOr(ByteArray(std::move(buffer))); + } + + if (bytes_read == 0) { + // EOF / peer closed. + return ExceptionOr(ByteArray(std::string())); + } + + if (errno == EINTR) { + continue; + } + + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // Non-blocking fd had no data by the time recv() ran. + // Go back to poll. + continue; + } + + LOG(ERROR) << __func__ << ": recv failed: " << std::strerror(errno); + return {Exception::kIo}; + } + } } Exception InputStream::Close() { - if (!fd_.isValid()) return Exception{Exception::kIo}; + if (!fd_->isValid()) return Exception{Exception::kIo}; fd_.reset(); return {}; } Exception OutputStream::Write(absl::string_view data) { - if (!fd_.isValid()) return Exception{Exception::kIo}; - - size_t written = 0; - while (written < data.size()) { - ssize_t ret = write(fd_.get(), data.data(), data.size()); - if (ret < 0) { - LOG(ERROR) << __func__ - << ": error writing to fd: " << std::strerror(errno); - return Exception{Exception::kIo}; - } - written += ret; + if (!fd_ || !fd_->isValid()) { + return {Exception::kIo}; } - return Exception{Exception::kSuccess}; + + const int fd = fd_->get(); + size_t sent = 0; + + while (sent < data.size()) { + pollfd pfd{}; + pfd.fd = fd; + pfd.events = POLLOUT; + + int poll_result; + do { + poll_result = poll(&pfd, 1, -1); + } while (poll_result < 0 && errno == EINTR); + + if (poll_result < 0) { + LOG(ERROR) << __func__ + << ": poll failed: " << std::strerror(errno); + return {Exception::kIo}; + } + + if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { + LOG(ERROR) << __func__ + << ": fd error/hangup during write, revents=" << pfd.revents; + return {Exception::kIo}; + } + + if (!(pfd.revents & POLLOUT)) { + continue; + } + + ssize_t n = send( + fd, + data.data() + sent, + data.size() - sent, + MSG_NOSIGNAL); + + if (n > 0) { + sent += static_cast(n); + continue; + } + + if (n == 0) { + LOG(ERROR) << __func__ << ": send returned 0"; + return {Exception::kIo}; + } + + if (errno == EINTR) { + continue; + } + + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // Socket became not writable after poll said it was writable. + // Normal for non-blocking FDs. Go back to poll(). + continue; + } + + LOG(ERROR) << __func__ + << ": error writing to fd: " << std::strerror(errno); + return {Exception::kIo}; + } + + return {Exception::kSuccess}; } Exception OutputStream::Flush() { return Exception{Exception::kSuccess}; } Exception OutputStream::Close() { - if (!fd_.isValid()) return Exception{Exception::kIo}; + if (!fd_->isValid()) return Exception{Exception::kIo}; - auto ret = close(fd_.get()) < 0 ? Exception{Exception::kIo} + auto ret = close(fd_->get()) < 0 ? Exception{Exception::kIo} : Exception{Exception::kSuccess}; fd_.reset(); return ret; diff --git a/internal/platform/implementation/linux/stream.h b/internal/platform/implementation/linux/stream.h index 66d1c20c..b4b42f19 100644 --- a/internal/platform/implementation/linux/stream.h +++ b/internal/platform/implementation/linux/stream.h @@ -26,26 +26,26 @@ namespace nearby { namespace linux { class InputStream : public nearby::InputStream { public: - explicit InputStream(sdbus::UnixFd fd) : fd_(std::move(fd)){}; + explicit InputStream(sdbus::UnixFd fd) : fd_(std::make_shared(fd)){}; ExceptionOr Read(std::int64_t size) override; Exception Close() override; private: - sdbus::UnixFd fd_; + std::shared_ptr fd_; }; class OutputStream : public nearby::OutputStream { public: - explicit OutputStream(sdbus::UnixFd fd) : fd_(std::move(fd)){}; + explicit OutputStream(sdbus::UnixFd fd) : fd_(std::make_shared(fd)){}; Exception Write(absl::string_view data) override; Exception Flush() override; Exception Close() override; private: - sdbus::UnixFd fd_; + std::shared_ptr fd_; }; } // namespace linux diff --git a/internal/platform/implementation/linux/timer_test.cc b/internal/platform/implementation/linux/timer_test.cc index 60308d24..106df6e4 100644 --- a/internal/platform/implementation/linux/timer_test.cc +++ b/internal/platform/implementation/linux/timer_test.cc @@ -14,12 +14,11 @@ #include "internal/platform/implementation/timer.h" -#include // NOLINT -// NOLINT #include -#include // NOLINT #include "gtest/gtest.h" +#include "absl/time/time.h" +#include "internal/platform/count_down_latch.h" #include "internal/platform/implementation/platform.h" namespace nearby { @@ -38,29 +37,21 @@ TEST(Timer, TestCreateTimer) { } // This test case cannot run on Google3 -TEST(Timer, DISABLED_TestRepeatTimer) { +TEST(Timer, TestRepeatTimer) { + CountDownLatch latch(3); int count = 0; - std::unique_ptr timer = nearby::api::ImplementationPlatform::CreateTimer(); ASSERT_TRUE(timer != nullptr); - EXPECT_TRUE(timer->Create(300, 300, [&]() { ++count; })); - std::this_thread::sleep_for(std::chrono::seconds(1)); - EXPECT_TRUE(timer->Stop()); + EXPECT_TRUE(timer->Create(300, 300, [&]() { + ++count; + latch.CountDown(); + })); + + EXPECT_TRUE(latch.Await(absl::Seconds(2))); EXPECT_EQ(count, 3); -} - -TEST(Timer, DISABLED_TestFireNow) { - int count = 0; - - auto timer = nearby::api::ImplementationPlatform::CreateTimer(); - - EXPECT_TRUE(timer != nullptr); - EXPECT_TRUE(timer->Create(3000, 3000, [&]() { ++count; })); - EXPECT_TRUE(timer->FireNow()); EXPECT_TRUE(timer->Stop()); - EXPECT_EQ(count, 1); } } // namespace diff --git a/sharing/linux/BUILD b/sharing/linux/BUILD index 2ea5d434..29f06fc4 100644 --- a/sharing/linux/BUILD +++ b/sharing/linux/BUILD @@ -16,6 +16,23 @@ licenses(["notice"]) load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") load("@rules_cc//cc/private/rules_impl:cc_static_library.bzl", "cc_static_library") +load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands") + +refresh_compile_commands( + name = "refresh_compile_commands_sharing", + + # Specify the targets of interest. + # For example, specify a dict of targets and any flags required to build. + targets = { + ":nearby_sharing_api_shared": "-s --check_visibility=false --spawn_strategy=standalone --verbose_failures --cxxopt=-std=c++20 --host_cxxopt=-std=c++20 --cxxopt='-fvisibility-inlines-hidden'", + }, + # No need to add flags already in .bazelrc. They're automatically picked up. + # If you don't need flags, a list of targets is also okay, as is a single target string. + # Wildcard patterns, like //... for everything, *are* allowed here, just like a build. + # As are additional targets (+) and subtractions (-), like in bazel query https://docs.bazel.build/versions/main/query.html#expressions + # And if you're working on a header-only library, specify a test or binary target that compiles it. +) + cc_library( name = "linux_sharing_platform", srcs = ["platform/linux_sharing_platform.cc"],