feat: 修复启动bash路径、将丢失连接时的视频稍微不堆积
This commit is contained in:
@@ -174,7 +174,7 @@ def test_kcp_idle_video_peers_survive_without_receive_loop() -> None:
|
|||||||
port = _reserve_port()
|
port = _reserve_port()
|
||||||
listen_addr = f'127.0.0.1:{port}'
|
listen_addr = f'127.0.0.1:{port}'
|
||||||
sender_id = 'peer-b-video'
|
sender_id = 'peer-b-video'
|
||||||
receiver_id = 'peer-a-video'
|
receiver_id = 'pytest-kcp-video-idle-receiver'
|
||||||
|
|
||||||
with _run_server('kcpserver', listen_addr):
|
with _run_server('kcpserver', listen_addr):
|
||||||
sender = _connect_with_retry(Session, transport='kcp', server_addr=listen_addr, peer_id=sender_id)
|
sender = _connect_with_retry(Session, transport='kcp', server_addr=listen_addr, peer_id=sender_id)
|
||||||
@@ -194,6 +194,22 @@ def test_kcp_idle_video_peers_survive_without_receive_loop() -> None:
|
|||||||
receiver.close()
|
receiver.close()
|
||||||
|
|
||||||
|
|
||||||
|
def test_kcp_peer_a_video_stale_receiver_is_evicted() -> None:
|
||||||
|
port = _reserve_port()
|
||||||
|
listen_addr = f'127.0.0.1:{port}'
|
||||||
|
receiver_id = 'peer-a-video'
|
||||||
|
|
||||||
|
with _run_server('kcpserver', listen_addr):
|
||||||
|
receiver = _connect_with_retry(Session, transport='kcp', server_addr=listen_addr, peer_id=receiver_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
time.sleep(5.0)
|
||||||
|
with pytest.raises(OSError):
|
||||||
|
receiver.recv(timeout_ms=1000)
|
||||||
|
finally:
|
||||||
|
receiver.close()
|
||||||
|
|
||||||
|
|
||||||
def test_udp_session_close_interrupts_blocking_recv() -> None:
|
def test_udp_session_close_interrupts_blocking_recv() -> None:
|
||||||
port = _reserve_port()
|
port = _reserve_port()
|
||||||
listen_addr = f'127.0.0.1:{port}'
|
listen_addr = f'127.0.0.1:{port}'
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ The scripts assume:
|
|||||||
- `robot-command-center` is a sibling directory next to it
|
- `robot-command-center` is a sibling directory next to it
|
||||||
|
|
||||||
If your `robot-command-center` is elsewhere, set `ROBOT_COMMAND_CENTER_ROOT` in `robot-remote.env.local`.
|
If your `robot-command-center` is elsewhere, set `ROBOT_COMMAND_CENTER_ROOT` in `robot-remote.env.local`.
|
||||||
|
`start-backend.sh` and `start-frontend.sh` need that repo; `start-ros-receiver.sh` and `start-b-side-omnid.sh` do not.
|
||||||
|
|
||||||
## Files
|
## Files
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ is_robot_command_center_root() {
|
|||||||
[[ -f "${dir}/backend/config/asgi.py" && -f "${dir}/frontend/package.json" ]]
|
[[ -f "${dir}/backend/config/asgi.py" && -f "${dir}/frontend/package.json" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require_robot_command_center_root() {
|
||||||
|
if ! is_robot_command_center_root "${ROBOT_COMMAND_CENTER_ROOT}"; then
|
||||||
|
die "ROBOT_COMMAND_CENTER_ROOT must point to the robot-command-center repo root. Current value: ${ROBOT_COMMAND_CENTER_ROOT}. Set it in ${SCRIPT_DIR}/robot-remote.env.local if needed."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
export OMNISOCKETGO_ROOT="${OMNISOCKETGO_ROOT:-${DEFAULT_OMNISOCKETGO_ROOT}}"
|
export OMNISOCKETGO_ROOT="${OMNISOCKETGO_ROOT:-${DEFAULT_OMNISOCKETGO_ROOT}}"
|
||||||
|
|
||||||
ENV_FILES=(
|
ENV_FILES=(
|
||||||
@@ -42,10 +48,6 @@ if ! is_omnisocketgo_root "${OMNISOCKETGO_ROOT}"; then
|
|||||||
die "OMNISOCKETGO_ROOT must point to the OmniSocketGo repo root. Current value: ${OMNISOCKETGO_ROOT}"
|
die "OMNISOCKETGO_ROOT must point to the OmniSocketGo repo root. Current value: ${OMNISOCKETGO_ROOT}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! is_robot_command_center_root "${ROBOT_COMMAND_CENTER_ROOT}"; then
|
|
||||||
die "ROBOT_COMMAND_CENTER_ROOT must point to the robot-command-center repo root. Current value: ${ROBOT_COMMAND_CENTER_ROOT}. Set it in ${SCRIPT_DIR}/robot-remote.env.local if needed."
|
|
||||||
fi
|
|
||||||
|
|
||||||
export BACKEND_DIR="${BACKEND_DIR:-${ROBOT_COMMAND_CENTER_ROOT}/backend}"
|
export BACKEND_DIR="${BACKEND_DIR:-${ROBOT_COMMAND_CENTER_ROOT}/backend}"
|
||||||
export FRONTEND_DIR="${FRONTEND_DIR:-${ROBOT_COMMAND_CENTER_ROOT}/frontend}"
|
export FRONTEND_DIR="${FRONTEND_DIR:-${ROBOT_COMMAND_CENTER_ROOT}/frontend}"
|
||||||
export ROS_CONTROL_PY_DIR="${ROS_CONTROL_PY_DIR:-${OMNISOCKETGO_ROOT}/ros-control-py}"
|
export ROS_CONTROL_PY_DIR="${ROS_CONTROL_PY_DIR:-${OMNISOCKETGO_ROOT}/ros-control-py}"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ set -euo pipefail
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
source "${SCRIPT_DIR}/load-env.sh"
|
source "${SCRIPT_DIR}/load-env.sh"
|
||||||
|
require_robot_command_center_root
|
||||||
|
|
||||||
if [[ ! -d "${PYTHON_VENV_PATH}" ]]; then
|
if [[ ! -d "${PYTHON_VENV_PATH}" ]]; then
|
||||||
"${PYTHON3_BIN}" -m venv "${PYTHON_VENV_PATH}"
|
"${PYTHON3_BIN}" -m venv "${PYTHON_VENV_PATH}"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ set -euo pipefail
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
source "${SCRIPT_DIR}/load-env.sh"
|
source "${SCRIPT_DIR}/load-env.sh"
|
||||||
|
require_robot_command_center_root
|
||||||
|
|
||||||
cd "${FRONTEND_DIR}"
|
cd "${FRONTEND_DIR}"
|
||||||
exec npm run dev -- --host "${FRONTEND_HOST}" --port "${FRONTEND_PORT}"
|
exec npm run dev -- --host "${FRONTEND_HOST}" --port "${FRONTEND_PORT}"
|
||||||
|
|||||||
@@ -113,11 +113,17 @@ static int kcp_hub_peer_is_telemetry(const char *peer_id) {
|
|||||||
return kcp_hub_peer_id_has_suffix(peer_id, "-telemetry");
|
return kcp_hub_peer_id_has_suffix(peer_id, "-telemetry");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int kcp_hub_peer_is_video_receiver(const char *peer_id) {
|
||||||
|
return peer_id != NULL && strcmp(peer_id, "peer-a-video") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int kcp_hub_peer_uses_server_lease(const char *peer_id) {
|
static int kcp_hub_peer_uses_server_lease(const char *peer_id) {
|
||||||
if (peer_id == NULL || peer_id[0] == '\0') {
|
if (peer_id == NULL || peer_id[0] == '\0') {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return kcp_hub_peer_id_has_suffix(peer_id, "-ctrl") || kcp_hub_peer_is_telemetry(peer_id);
|
return kcp_hub_peer_id_has_suffix(peer_id, "-ctrl")
|
||||||
|
|| kcp_hub_peer_is_telemetry(peer_id)
|
||||||
|
|| kcp_hub_peer_is_video_receiver(peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *kcp_hub_peer_node_id(const char *peer_id) {
|
static const char *kcp_hub_peer_node_id(const char *peer_id) {
|
||||||
|
|||||||
@@ -566,6 +566,32 @@ static int video_sender_init(video_sender_t *sender, const video_pipeline_config
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int video_sender_drain_pending_messages(video_sender_t *sender) {
|
||||||
|
if (sender == NULL || sender->client == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
message_t msg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
protocol_message_init(&msg);
|
||||||
|
rc = kcp_client_receive_timed(sender->client, &msg, 1);
|
||||||
|
if (rc == 1) {
|
||||||
|
protocol_message_clear(&msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (rc != 0) {
|
||||||
|
protocol_message_clear(&msg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drain unread server errors so an offline receiver cannot back up the reverse KCP stream.
|
||||||
|
protocol_message_clear(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int video_sender_send_packet(video_sender_t *sender, const AVPacket *encoded_pkt, uint64_t timestamp) {
|
static int video_sender_send_packet(video_sender_t *sender, const AVPacket *encoded_pkt, uint64_t timestamp) {
|
||||||
uint8_t *payload;
|
uint8_t *payload;
|
||||||
size_t payload_len;
|
size_t payload_len;
|
||||||
@@ -585,6 +611,10 @@ static int video_sender_send_packet(video_sender_t *sender, const AVPacket *enco
|
|||||||
memcpy(payload, encoded_pkt->data, (size_t) encoded_pkt->size);
|
memcpy(payload, encoded_pkt->data, (size_t) encoded_pkt->size);
|
||||||
memcpy(payload + encoded_pkt->size, ×tamp, sizeof(timestamp));
|
memcpy(payload + encoded_pkt->size, ×tamp, sizeof(timestamp));
|
||||||
rc = kcp_client_send_binary(sender->client, sender->target_peer, payload, payload_len);
|
rc = kcp_client_send_binary(sender->client, sender->target_peer, payload, payload_len);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = video_sender_drain_pending_messages(sender);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -566,6 +566,32 @@ static int video_sender_init(video_sender_t *sender, const video_pipeline_config
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int video_sender_drain_pending_messages(video_sender_t *sender) {
|
||||||
|
if (sender == NULL || sender->client == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
message_t msg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
protocol_message_init(&msg);
|
||||||
|
rc = kcp_client_receive_timed(sender->client, &msg, 1);
|
||||||
|
if (rc == 1) {
|
||||||
|
protocol_message_clear(&msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (rc != 0) {
|
||||||
|
protocol_message_clear(&msg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drain unread server errors so an offline receiver cannot back up the reverse KCP stream.
|
||||||
|
protocol_message_clear(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int video_sender_send_packet(video_sender_t *sender, const AVPacket *encoded_pkt, uint64_t timestamp) {
|
static int video_sender_send_packet(video_sender_t *sender, const AVPacket *encoded_pkt, uint64_t timestamp) {
|
||||||
uint8_t *payload;
|
uint8_t *payload;
|
||||||
size_t payload_len;
|
size_t payload_len;
|
||||||
@@ -585,6 +611,10 @@ static int video_sender_send_packet(video_sender_t *sender, const AVPacket *enco
|
|||||||
memcpy(payload, encoded_pkt->data, (size_t) encoded_pkt->size);
|
memcpy(payload, encoded_pkt->data, (size_t) encoded_pkt->size);
|
||||||
memcpy(payload + encoded_pkt->size, ×tamp, sizeof(timestamp));
|
memcpy(payload + encoded_pkt->size, ×tamp, sizeof(timestamp));
|
||||||
rc = kcp_client_send_binary(sender->client, sender->target_peer, payload, payload_len);
|
rc = kcp_client_send_binary(sender->client, sender->target_peer, payload, payload_len);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = video_sender_drain_pending_messages(sender);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user