Skip to content

Instantly share code, notes, and snippets.

@mgood7123
Created November 30, 2022 09:23
Show Gist options
  • Save mgood7123/e0ced62f87d4a8c72826f20562d53e9e to your computer and use it in GitHub Desktop.
Save mgood7123/e0ced62f87d4a8c72826f20562d53e9e to your computer and use it in GitHub Desktop.
int
wl_connection_flush(struct wl_connection *connection)
{
struct iovec iov[2];
int len = 0, count;
size_t clen;
uint32_t tail;
if (!connection->want_flush)
return 0;
tail = connection->out.tail;
uid_t uid = 0; gid_t gid = 0; pid_t pid = 0;
struct wl_ring_buffer * buffer = &connection->fds_out;
struct RING_BUFFER_FD_STORAGE s = {0};
RING_BUFFER_INIT_STORAGE(buffer, s);
if (s.len > 0) {
wl_os_socket_peercred(connection->fd, &uid, &gid, &pid);
}
if (s.len > 0) {
// send fd's first
size_t handle_array_item_size = sizeof(FD_HANDLE_T);
size_t handle_array_bytes = handle_array_item_size * s.len;
FD_HANDLE_T * handle_array = zalloc(handle_array_bytes);
FD_HANDLE_T * handle_array_start = handle_array;
int handle_count = 0;
size_t socket_array_item_size = sizeof(WSAPROTOCOL_INFO);
size_t socket_array_bytes = socket_array_item_size * s.len;
WSAPROTOCOL_INFO * socket_array = zalloc(socket_array_bytes);
WSAPROTOCOL_INFO * socket_array_start = socket_array;
int socket_count = 0;
for (FD_HANDLE_T * fd = RING_BUFFER_GET_NEXT_FD(s); fd != NULL; fd = RING_BUFFER_GET_NEXT_FD(s)) {
if (FD_HANDLE_IS_SOCKET(*fd)) {
if (WSADuplicateSocket(*fd, pid, socket_array_start) == SOCKET_ERROR) {
wl_log("WSADuplicateSocket(): failed. Error = %d\n", WSAGetLastError());
continue;
}
socket_array_start += socket_array_item_size;
socket_count++;
} else {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!DuplicateHandle(GetCurrentProcess(), *fd, hProcess, handle_array_start, DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS)) {
wl_log("DuplicateHandle(): failed. Error = %d\n", GetLastError());
CloseHandle(hProcess);
continue;
}
handle_array_start += handle_array_item_size;
handle_count++;
CloseHandle(hProcess);
}
}
bool has[2] = { socket_count != 0, handle_count != 0};
do {
len = send(connection->fd, has, sizeof(bool)*2, 0);
} while (len == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
if (has[0]) {
size_t size = socket_array_item_size * socket_count;
do {
len = send(connection->fd, size, sizeof(size_t), 0);
} while (len == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
do {
len = send(connection->fd, socket_array, size, 0);
} while (len == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
}
if (has[1]) {
size_t size = handle_array_item_size * handle_count;
do {
len = send(connection->fd, size, sizeof(size_t), 0);
} while (len == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
do {
len = send(connection->fd, handle_array, size, 0);
} while (len == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
}
free(handle_array);
free(socket_array);
close_fds(&connection->fds_out, MAX_FDS_OUT);
}
if (len == SOCKET_ERROR)
return -1;
// now send data
while (connection->out.head - connection->out.tail > 0) {
ring_buffer_get_iov(&connection->out, iov, &count);
if (len == SOCKET_ERROR)
return -1;
struct wl_ring_buffer * buffer = &connection->out;
do {
len = send(connection->fd, ring_buffer_size(buffer), sizeof(size_t), 0);
} while (len == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
do {
len = send(connection->fd, connection->out.data, ring_buffer_size(buffer), 0);
} while (len == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
connection->out.tail += len;
}
connection->want_flush = 0;
return connection->out.head - tail;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment