mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-04 06:06:17 +00:00
d/remote: Support r_hub for Windows
Signed-off-by: utzcoz <utzcoz@outlook.com>
This commit is contained in:
parent
d7468d22da
commit
58193ad1c4
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2020-2022, Collabora, Ltd.
|
// Copyright 2020-2023, Collabora, Ltd.
|
||||||
// SPDX-License-Identifier: BSL-1.0
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
/*!
|
/*!
|
||||||
* @file
|
* @file
|
||||||
|
@ -17,22 +17,34 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
|
#if defined(XRT_OS_WINDOWS)
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
|
#ifndef _BSD_SOURCE
|
||||||
|
#define _BSD_SOURCE // same, but for musl // NOLINT
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SOCKET
|
||||||
|
#define SOCKET int
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __USE_MISC
|
#ifndef __USE_MISC
|
||||||
#define __USE_MISC // SOL_TCP on C11
|
#define __USE_MISC // SOL_TCP on C11
|
||||||
#endif
|
#endif
|
||||||
#ifndef _BSD_SOURCE
|
|
||||||
#define _BSD_SOURCE // same, but for musl // NOLINT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -62,27 +74,100 @@ DEBUG_GET_ONCE_LOG_OPTION(remote_log, "REMOTE_LOG", U_LOGGING_INFO)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(XRT_OS_WINDOWS)
|
||||||
|
static void
|
||||||
|
socket_close(SOCKET id)
|
||||||
|
{
|
||||||
|
closesocket(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SOCKET
|
||||||
|
socket_create(void)
|
||||||
|
{
|
||||||
|
return socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_set_opt(SOCKET id, int flag)
|
||||||
|
{
|
||||||
|
return setsockopt(id, SOL_SOCKET, SO_REUSEADDR, (const char *)&flag, sizeof(flag));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
socket_read(SOCKET id, void *ptr, size_t size, size_t current)
|
||||||
|
{
|
||||||
|
return recv(id, (char *)ptr, size - current, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
socket_write(SOCKET id, void *ptr, size_t size, size_t current)
|
||||||
|
{
|
||||||
|
return send(id, (const char *)ptr, size - current, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static void
|
||||||
|
socket_close(SOCKET id)
|
||||||
|
{
|
||||||
|
close(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SOCKET
|
||||||
|
socket_create(void)
|
||||||
|
{
|
||||||
|
return socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_set_opt(SOCKET id, int flag)
|
||||||
|
{
|
||||||
|
return setsockopt(id, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
socket_read(SOCKET id, void *ptr, size_t size, size_t current)
|
||||||
|
{
|
||||||
|
return read(id, ptr, size - current);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
socket_write(SOCKET id, void *ptr, size_t size, size_t current)
|
||||||
|
{
|
||||||
|
return write(id, ptr, size - current);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
setup_accept_fd(struct r_hub *r)
|
setup_accept_fd(struct r_hub *r)
|
||||||
{
|
{
|
||||||
struct sockaddr_in server_address = {0};
|
struct sockaddr_in server_address = {0};
|
||||||
int ret;
|
#if defined(XRT_OS_WINDOWS)
|
||||||
|
// Initialize Winsock.
|
||||||
|
WSADATA wsaData;
|
||||||
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||||
|
int error = WSAGetLastError();
|
||||||
|
R_ERROR(r, "Failed to do WSAStartup %ld", error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
SOCKET ret = socket_create();
|
||||||
|
|
||||||
ret = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
R_ERROR(r, "socket: %i", ret);
|
R_ERROR(r, "socket: %i", ret);
|
||||||
return ret;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->accept_fd = ret;
|
r->accept_fd = ret;
|
||||||
|
|
||||||
int flag = 1;
|
int flag = 1;
|
||||||
ret = setsockopt(r->accept_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
|
ret = socket_set_opt(r->accept_fd, flag);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
R_ERROR(r, "setsockopt: %i", ret);
|
R_ERROR(r, "setsockopt: %i", ret);
|
||||||
close(r->accept_fd);
|
socket_close(r->accept_fd);
|
||||||
r->accept_fd = -1;
|
r->accept_fd = -1;
|
||||||
return ret;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
server_address.sin_family = AF_INET;
|
server_address.sin_family = AF_INET;
|
||||||
|
@ -92,18 +177,25 @@ setup_accept_fd(struct r_hub *r)
|
||||||
ret = bind(r->accept_fd, (struct sockaddr *)&server_address, sizeof(server_address));
|
ret = bind(r->accept_fd, (struct sockaddr *)&server_address, sizeof(server_address));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
R_ERROR(r, "bind: %i", ret);
|
R_ERROR(r, "bind: %i", ret);
|
||||||
close(r->accept_fd);
|
socket_close(r->accept_fd);
|
||||||
r->accept_fd = -1;
|
r->accept_fd = -1;
|
||||||
return ret;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R_INFO(r, "Listen address %s on port %d", inet_ntoa(server_address.sin_addr), r->port);
|
||||||
|
|
||||||
listen(r->accept_fd, 5);
|
listen(r->accept_fd, 5);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
cleanup:
|
||||||
|
#if defined(XRT_OS_WINDOWS)
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
wait_for_read_and_to_continue(struct r_hub *r, int socket)
|
wait_for_read_and_to_continue(struct r_hub *r, SOCKET socket)
|
||||||
{
|
{
|
||||||
fd_set set;
|
fd_set set;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -139,9 +231,8 @@ do_accept(struct r_hub *r)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr = {0};
|
struct sockaddr_in addr = {0};
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int conn_fd;
|
|
||||||
|
|
||||||
if (!wait_for_read_and_to_continue(r, r->accept_fd)) {
|
if (!wait_for_read_and_to_continue(r, r->accept_fd)) {
|
||||||
|
R_ERROR(r, "Failed to wait for id %d", r->accept_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,13 +243,13 @@ do_accept(struct r_hub *r)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn_fd = ret;
|
SOCKET conn_fd = ret;
|
||||||
|
|
||||||
int flags = 1;
|
int flags = 1;
|
||||||
ret = setsockopt(conn_fd, SOL_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
|
ret = socket_set_opt(r->accept_fd, flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
R_ERROR(r, "setsockopt: %i", ret);
|
R_ERROR(r, "setsockopt: %i", ret);
|
||||||
close(conn_fd);
|
socket_close(conn_fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,9 +275,13 @@ read_one(struct r_hub *r, struct r_remote_data *data)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t ret = read(rc->fd, ptr, size - current);
|
ssize_t ret = socket_read(rc->fd, ptr, size, current);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
#if defined(XRT_OS_WINDOWS)
|
||||||
|
RC_ERROR(rc, "recv: %zi", WSAGetLastError());
|
||||||
|
#else
|
||||||
RC_ERROR(rc, "read: %zi", ret);
|
RC_ERROR(rc, "read: %zi", ret);
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
} else if (ret > 0) {
|
} else if (ret > 0) {
|
||||||
current += (size_t)ret;
|
current += (size_t)ret;
|
||||||
|
@ -257,7 +352,7 @@ r_hub_system_devices_destroy(struct xrt_system_devices *xsysd)
|
||||||
|
|
||||||
// Should be safe to destroy the sockets now.
|
// Should be safe to destroy the sockets now.
|
||||||
if (r->accept_fd >= 0) {
|
if (r->accept_fd >= 0) {
|
||||||
close(r->accept_fd);
|
socket_close(r->accept_fd);
|
||||||
r->accept_fd = -1;
|
r->accept_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,6 +362,11 @@ r_hub_system_devices_destroy(struct xrt_system_devices *xsysd)
|
||||||
}
|
}
|
||||||
|
|
||||||
free(r);
|
free(r);
|
||||||
|
|
||||||
|
#if defined(XRT_OS_WINDOWS)
|
||||||
|
// Clean up Winsock.
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -359,7 +459,6 @@ r_create_devices(uint16_t port, struct xrt_system_devices **out_xsysd)
|
||||||
u_var_add_bool(r, &r->latest.right.active, "right.active");
|
u_var_add_bool(r, &r->latest.right.active, "right.active");
|
||||||
u_var_add_pose(r, &r->latest.right.pose, "right.pose");
|
u_var_add_pose(r, &r->latest.right.pose, "right.pose");
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Done now.
|
* Done now.
|
||||||
*/
|
*/
|
||||||
|
@ -386,42 +485,75 @@ r_remote_connection_init(struct r_remote_connection *rc, const char *ip_addr, ui
|
||||||
// Set log level.
|
// Set log level.
|
||||||
rc->log_level = debug_get_log_option_remote_log();
|
rc->log_level = debug_get_log_option_remote_log();
|
||||||
|
|
||||||
|
#if defined(XRT_OS_WINDOWS)
|
||||||
|
// Initialize Winsock.
|
||||||
|
WSADATA wsaData;
|
||||||
|
ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||||
|
if (ret != 0) {
|
||||||
|
RC_ERROR(rc, "Failed to do WSAStartup %ld", WSAGetLastError());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Address
|
// Address
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(port);
|
addr.sin_port = htons(port);
|
||||||
|
|
||||||
|
// inet_pton/InetPton resolves "localhost" as 0.0.0.0 or 255.255.255.255, and it causes connection error. To
|
||||||
|
// avoid this issue, the following logic converts "localhost" to "127.0.0.1" first.
|
||||||
|
if (strcmp("localhost", ip_addr) == 0) {
|
||||||
|
ret = inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
|
||||||
|
} else {
|
||||||
ret = inet_pton(AF_INET, ip_addr, &addr.sin_addr);
|
ret = inet_pton(AF_INET, ip_addr, &addr.sin_addr);
|
||||||
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
RC_ERROR(rc, "inet_pton: %i", ret);
|
RC_ERROR(rc, "Failed to do inet pton for %s: %i", ip_addr, ret);
|
||||||
return ret;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = socket(AF_INET, SOCK_STREAM, 0);
|
ret = socket_create();
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
RC_ERROR(rc, "socket: %i", ret);
|
#if defined(XRT_OS_WINDOWS)
|
||||||
return ret;
|
RC_ERROR(rc, "Failed to create socket %ld", WSAGetLastError());
|
||||||
|
#else
|
||||||
|
RC_ERROR(rc, "Failed to create socket: %i", ret);
|
||||||
|
#endif
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn_fd = ret;
|
conn_fd = ret;
|
||||||
|
|
||||||
ret = connect(conn_fd, (struct sockaddr *)&addr, sizeof(addr));
|
ret = connect(conn_fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
if (ret < 0) {
|
// If connect operation succeed, both Windows and POSIX returns 0.
|
||||||
RC_ERROR(rc, "connect: %i", ret);
|
if (ret != 0) {
|
||||||
close(conn_fd);
|
#if defined(XRT_OS_WINDOWS)
|
||||||
return ret;
|
RC_ERROR(rc, "Failed to connect id %d and addr %s with failure %d", conn_fd, inet_ntoa(addr.sin_addr),
|
||||||
|
WSAGetLastError());
|
||||||
|
#else
|
||||||
|
RC_ERROR(rc, "Failed to connect id %d and addr %s with failure %d", conn_fd, inet_ntoa(addr.sin_addr),
|
||||||
|
ret);
|
||||||
|
#endif
|
||||||
|
socket_close(conn_fd);
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flags = 1;
|
int flags = 1;
|
||||||
ret = setsockopt(conn_fd, SOL_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
|
ret = socket_set_opt(conn_fd, flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
RC_ERROR(rc, "setsockopt: %i", ret);
|
RC_ERROR(rc, "Failed to setsockopt: %i", ret);
|
||||||
close(conn_fd);
|
socket_close(conn_fd);
|
||||||
return ret;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc->fd = conn_fd;
|
rc->fd = conn_fd;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
#if defined(XRT_OS_WINDOWS)
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -432,8 +564,7 @@ r_remote_connection_read_one(struct r_remote_connection *rc, struct r_remote_dat
|
||||||
|
|
||||||
while (current < size) {
|
while (current < size) {
|
||||||
void *ptr = (uint8_t *)data + current;
|
void *ptr = (uint8_t *)data + current;
|
||||||
|
ssize_t ret = socket_read(rc->fd, ptr, size, current);
|
||||||
ssize_t ret = read(rc->fd, ptr, size - current);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
RC_ERROR(rc, "read: %zi", ret);
|
RC_ERROR(rc, "read: %zi", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -456,9 +587,9 @@ r_remote_connection_write_one(struct r_remote_connection *rc, const struct r_rem
|
||||||
size_t current = 0;
|
size_t current = 0;
|
||||||
|
|
||||||
while (current < size) {
|
while (current < size) {
|
||||||
const void *ptr = (const uint8_t *)data + current;
|
void *ptr = (uint8_t *)data + current;
|
||||||
|
|
||||||
ssize_t ret = write(rc->fd, ptr, size - current);
|
ssize_t ret = socket_write(rc->fd, ptr, size, current);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
RC_ERROR(rc, "write: %zi", ret);
|
RC_ERROR(rc, "write: %zi", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue