d/remote: Support r_hub for Windows

Signed-off-by: utzcoz <utzcoz@outlook.com>
This commit is contained in:
utzcoz 2023-03-25 15:36:34 +08:00 committed by Jakob Bornecrantz
parent d7468d22da
commit 58193ad1c4

View file

@ -1,4 +1,4 @@
// Copyright 2020-2022, Collabora, Ltd.
// Copyright 2020-2023, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
@ -17,22 +17,34 @@
#include <stdio.h>
#include <stdlib.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/types.h>
#include <netdb.h>
#include <arpa/inet.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
#define __USE_MISC // SOL_TCP on C11
#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
setup_accept_fd(struct r_hub *r)
{
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) {
R_ERROR(r, "socket: %i", ret);
return ret;
goto cleanup;
}
r->accept_fd = ret;
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) {
R_ERROR(r, "setsockopt: %i", ret);
close(r->accept_fd);
socket_close(r->accept_fd);
r->accept_fd = -1;
return ret;
goto cleanup;
}
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));
if (ret < 0) {
R_ERROR(r, "bind: %i", ret);
close(r->accept_fd);
socket_close(r->accept_fd);
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);
return 0;
cleanup:
#if defined(XRT_OS_WINDOWS)
WSACleanup();
#endif
return ret;
}
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;
int ret = 0;
@ -139,9 +231,8 @@ do_accept(struct r_hub *r)
{
struct sockaddr_in addr = {0};
int ret = 0;
int conn_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;
}
@ -152,13 +243,13 @@ do_accept(struct r_hub *r)
return ret;
}
conn_fd = ret;
SOCKET conn_fd = ret;
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) {
R_ERROR(r, "setsockopt: %i", ret);
close(conn_fd);
socket_close(conn_fd);
return ret;
}
@ -184,9 +275,13 @@ read_one(struct r_hub *r, struct r_remote_data *data)
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 defined(XRT_OS_WINDOWS)
RC_ERROR(rc, "recv: %zi", WSAGetLastError());
#else
RC_ERROR(rc, "read: %zi", ret);
#endif
return ret;
} else if (ret > 0) {
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.
if (r->accept_fd >= 0) {
close(r->accept_fd);
socket_close(r->accept_fd);
r->accept_fd = -1;
}
@ -267,6 +362,11 @@ r_hub_system_devices_destroy(struct xrt_system_devices *xsysd)
}
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_pose(r, &r->latest.right.pose, "right.pose");
/*
* Done now.
*/
@ -386,42 +485,75 @@ r_remote_connection_init(struct r_remote_connection *rc, const char *ip_addr, ui
// Set log level.
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
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
ret = inet_pton(AF_INET, ip_addr, &addr.sin_addr);
// 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);
}
if (ret < 0) {
RC_ERROR(rc, "inet_pton: %i", ret);
return ret;
RC_ERROR(rc, "Failed to do inet pton for %s: %i", ip_addr, ret);
goto cleanup;
}
ret = socket(AF_INET, SOCK_STREAM, 0);
ret = socket_create();
if (ret < 0) {
RC_ERROR(rc, "socket: %i", ret);
return ret;
#if defined(XRT_OS_WINDOWS)
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;
ret = connect(conn_fd, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
RC_ERROR(rc, "connect: %i", ret);
close(conn_fd);
return ret;
// If connect operation succeed, both Windows and POSIX returns 0.
if (ret != 0) {
#if defined(XRT_OS_WINDOWS)
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;
ret = setsockopt(conn_fd, SOL_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
ret = socket_set_opt(conn_fd, flags);
if (ret < 0) {
RC_ERROR(rc, "setsockopt: %i", ret);
close(conn_fd);
return ret;
RC_ERROR(rc, "Failed to setsockopt: %i", ret);
socket_close(conn_fd);
goto cleanup;
}
rc->fd = conn_fd;
return 0;
cleanup:
#if defined(XRT_OS_WINDOWS)
WSACleanup();
#endif
return ret;
}
int
@ -432,8 +564,7 @@ r_remote_connection_read_one(struct r_remote_connection *rc, struct r_remote_dat
while (current < size) {
void *ptr = (uint8_t *)data + current;
ssize_t ret = read(rc->fd, ptr, size - current);
ssize_t ret = socket_read(rc->fd, ptr, size, current);
if (ret < 0) {
RC_ERROR(rc, "read: %zi", 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;
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) {
RC_ERROR(rc, "write: %zi", ret);
return ret;