Skip to content

Commit

Permalink
Overhaul for stable networking architecture
Browse files Browse the repository at this point in the history
Old UDP based infrastructure removed. The new protocol is split between:
TCP: Favored for FIFO buffer transfer
UDP: Favored for framebuffer transfer

The new network architecture is stable enough to remove the
recommendations in the README against using it exclusively.

Extras:
- Fixed formatting in kernel module for Linux
- Made note in README about GLX symlink
  • Loading branch information
dmaivel committed May 27, 2024
1 parent b7dfb6c commit 3f4ef78
Show file tree
Hide file tree
Showing 8 changed files with 615 additions and 689 deletions.
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,18 +178,16 @@ There are two ways to install the library on windows:
```
# Networking
> [!WARNING]\
> The network protocol is currently in active early development and is prone to bugs.
Starting from `0.5.0`, SharedGL offers a networking feature that may be used in place of shared memory. No additional drivers are required for the network feature, meaning if you wish to have a driverless experience in your virtual machine, networking is the given alternative. If the networking feature is used exclusively **(NOT RECOMMENDED)**, the kernel drivers do not need be compiled/installed. However, installation of the ICD for either Linux or Windows is still required.
Starting from `0.5.0`, SharedGL offers a networking feature that may be used in place of shared memory. No additional drivers are required for the network feature, meaning if you wish to have a driverless experience in your virtual machine, networking is the given alternative. If the networking feature is used exclusively, the kernel drivers do not need be compiled/installed. However, installation of the ICD for either Linux or Windows is still required.
- Start the server using `-n` (and provide a port if the default is not available through `-p PORT`)
- Ensure the client libraries are installed
- Ensure that the environment variable `SGL_NET_OVER_SHARED=ADDRESS:PORT` exists in the guest (`ADDRESS` being the host's IP address)
# Virtual machines
> [!NOTE]\
> If the networking feature is used exclusively **(NOT RECOMMENDED)**, this step can be skipped.
> If the networking feature is used exclusively, this step can be skipped.
Before starting the virtual machine, you must pass a shared memory device and start the server before starting the virtual machine. This can be done within libvirt's XML editor or the command line. Before starting the virtual machine, start the server using `-v`, which will start the server and print the necessary configurations:
Expand Down Expand Up @@ -249,8 +247,8 @@ This list describes the amount of functions left from each standard to implement
- No Vsync
- Resizing is possible, no proper implementation
- Some GLFW applications cant request OpenGL profiles
- Networking is experimental, applications will halt after some time
- New GLX FB configs may cause applications using `freeglut` or `glad` to no longer run
- Some applications may require an explicit `libGLX`, so run `ln -s libGL.so.1 libGLX.so.0` in `build` to make a symlink.
# Troubleshooting
You may encounter weird crashes/faults/errors such as `IOT instruction` or `No provider of glXXX found.`. Although the code base is buggy, these are some tips to try to further attempts to get an application to work:
Expand Down
46 changes: 38 additions & 8 deletions inc/network/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@
#define NET_DONTWAIT 0x40

/*
* opaque; contents do not need to be seen or accessed
*
* this is for includes sake, we only need to include network
* stuff in the net.c file, instead of scattered around the
* project
* opaque; so we don't include network headers everywhere
*/
struct net_context;

int net_generate_signature();
#define NET_SOCKET_SERVER -1
#define NET_SOCKET_NONE -2
#define NET_SOCKET_FIRST_FD 2
typedef int net_socket;

enum net_poll_reason {
NET_POLL_FAILED = 0,
NET_POLL_INCOMING_CONNECTION = (1 << 0),
NET_POLL_INCOMING_UDP = (1 << 1),
NET_POLL_INCOMING_TCP = (1 << 2)
};

#ifndef _WIN32
char *net_get_ip();
Expand All @@ -24,7 +30,31 @@ char *net_get_ip();
char *net_init_server(struct net_context **ctx, int port);
char *net_init_client(struct net_context **ctx, char *hostname, int port);

long net_recvfrom(struct net_context *ctx, void *__restrict __buf, size_t __n, int __flags);
long net_sendto(struct net_context *ctx, const void *__buf, size_t __n, int __flags);
/*
* SERVER-specific
* hide from windows, need WSAPoll support first
*/
#ifndef _WIN32
enum net_poll_reason net_poll(struct net_context *ctx);
net_socket net_accept(struct net_context *ctx);
int net_fd_count(struct net_context *ctx);
bool net_did_event_happen_here(struct net_context *ctx, int fd);
#endif

// SERVER
void net_close(struct net_context *ctx, int fd);

// CLIENT
// void net_goodbye(struct net_context *ctx);

// UDP
long net_recv_udp(struct net_context *ctx, void *__restrict __buf, size_t __n, int __flags);
long net_send_udp(struct net_context *ctx, const void *__buf, size_t __n, int __flags);
long net_recv_udp_timeout(struct net_context *ctx, void *__restrict __buf, size_t __n, int __flags, size_t timeout_ms);

// TCP
bool net_recv_tcp(struct net_context *ctx, int fd, void *__restrict __buf, size_t __n);
bool net_send_tcp(struct net_context *ctx, int fd, const void *__buf, size_t __n);
bool net_recv_tcp_timeout(struct net_context *ctx, int fd, void *__restrict __buf, size_t __n, size_t timeout_ms);

#endif
87 changes: 46 additions & 41 deletions inc/network/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,15 @@
#define _SGL_PACKET_H_

#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>

/*
* 1024 * 63
*/
#define SGL_PACKET_MAX_BLOCK_SIZE 64512

#define SGL_PACKET_MAX_SIZE SGL_PACKET_MAX_BLOCK_SIZE + sizeof(struct sgl_packet_header)

enum {
/*
* notify server of our existence
* server sends this identical packet back (with the same signature) containing the client id
*/
SGL_PACKET_TYPE_CONNECT,

/*
* upload fifo buffer to server
* server tells client fifo stuff is done
*
* NOTE: RETVAL IS RETURNED TO THE CLIENT
*/
SGL_PACKET_TYPE_FIFO_UPLOAD,

/*
* request framebuffer from server
* - slow_but_safe: send small safe packets, min risk
* - fast_but_loss: send big packets, risk loss
*/
SGL_PACKET_TYPE_FRAMEBUFFER_SLOW_BUT_SAFE,
SGL_PACKET_TYPE_FRAMEBUFFER_FAST_BUT_LOSS,
SGL_PACKET_TYPE_FRAMEBUFFER_DONE,

/*
* request missing data
*/
SGL_PACKET_TYPE_REQUEST_RECOVERY,
};
#define SGL_FIFO_UPLOAD_COMMAND_BLOCK_COUNT 512
#define SGL_FIFO_UPLOAD_COMMAND_BLOCK_SIZE (SGL_FIFO_UPLOAD_COMMAND_BLOCK_COUNT * sizeof(uint32_t))
#define SGL_SWAPBUFFERS_RESULT_SIZE 60000

#ifndef _WIN32
#define PACKED __attribute__((packed))
Expand All @@ -49,14 +21,47 @@ enum {
#ifdef _WIN32
__pragma( pack(push, 1) )
#endif
struct PACKED sgl_packet_header {
short client_id;
bool is_for_server;
char type;
unsigned int size;
short index;
unsigned short expected_blocks;
int signature;
struct PACKED sgl_packet_connect {
uint32_t client_id;
uint64_t framebuffer_size;
uint64_t fifo_size;
uint32_t gl_major;
uint32_t gl_minor;
};

struct PACKED sgl_packet_swapbuffers_request {
uint32_t client_id;
uint32_t width;
uint32_t height;
uint32_t vflip;
uint32_t format;
};

struct PACKED sgl_packet_swapbuffers_result {
uint32_t client_id;
uint32_t index;
uint32_t size;
uint8_t result[SGL_SWAPBUFFERS_RESULT_SIZE];
};

struct PACKED sgl_packet_fifo_upload {
uint32_t client_id;
uint32_t expected_chunks;
uint32_t index;
uint32_t count;
uint32_t commands[SGL_FIFO_UPLOAD_COMMAND_BLOCK_COUNT];
};

struct PACKED sgl_packet_retval {
union {
uint32_t retval_split[2];
uint64_t retval;
};
uint32_t retval_v[256 / sizeof(uint32_t)];
};

struct PACKED sgl_packet_sync {
uint32_t sync;
};
#ifdef _WIN32
__pragma( pack(pop))
Expand Down
4 changes: 2 additions & 2 deletions kernel/linux/sharedgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ static struct pci_device_id pci_ids[] = {
static struct pci_driver pchar_driver = {
.name = "sharedgl",
.id_table = pci_ids,
.probe = pci_probe,
.remove = pci_remove,
.probe = pci_probe,
.remove = pci_remove,
};

static char *pci_char_devnode(const struct device *dev, umode_t *mode)
Expand Down
Loading

0 comments on commit 3f4ef78

Please sign in to comment.