[client] client is now opens shared memory from ivshmem passed fd

This commit is contained in:
Geoffrey McRae 2017-10-19 17:06:42 +11:00
parent 48facb3746
commit 3dd061b895
4 changed files with 162 additions and 47 deletions

View File

@ -9,13 +9,27 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <sys/stat.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/mman.h>
struct IVSHMEMServer
{
int64_t version;
int64_t clientID;
int sharedFD;
};
struct IVSHMEM struct IVSHMEM
{ {
bool connected; bool connected;
int socket; int socket;
struct IVSHMEMServer server;
off_t mapSize;
void * map;
}; };
struct IVSHMEM ivshmem = struct IVSHMEM ivshmem =
@ -29,6 +43,7 @@ struct IVSHMEM ivshmem =
void ivshmem_cleanup(); void ivshmem_cleanup();
bool ivshmem_read(void * buffer, const ssize_t size); bool ivshmem_read(void * buffer, const ssize_t size);
bool ivshmem_read_msg(int64_t * index, int *fd);
// ============================================================================ // ============================================================================
@ -54,46 +69,62 @@ bool ivshmem_connect(const char * unix_socket)
ivshmem.connected = true; ivshmem.connected = true;
struct IVSHMEMInit init; if (!ivshmem_read(&ivshmem.server.version, sizeof(ivshmem.server.version)))
if (!ivshmem_read(&init.version, sizeof(init.version)))
{ {
DEBUG_ERROR("read protocol version failed"); DEBUG_ERROR("read protocol version failed");
ivshmem_cleanup(); ivshmem_cleanup();
return false; return false;
} }
if (init.version != 0) if (ivshmem.server.version != 0)
{ {
DEBUG_ERROR("unsupported protocol version %ld", init.version); DEBUG_ERROR("unsupported protocol version %ld", ivshmem.server.version);
ivshmem_cleanup(); ivshmem_cleanup();
return false; return false;
} }
if (!ivshmem_read(&init.clientID, sizeof(init.clientID))) if (!ivshmem_read(&ivshmem.server.clientID, sizeof(ivshmem.server.clientID)))
{ {
DEBUG_ERROR("read client id failed"); DEBUG_ERROR("read client id failed");
ivshmem_cleanup(); ivshmem_cleanup();
return false; return false;
} }
if (!ivshmem_read(&init.unused, sizeof(init.unused))) DEBUG_PROTO("Protocol : %ld", ivshmem.server.version );
DEBUG_PROTO("Client ID: %ld", ivshmem.server.clientID);
if (!ivshmem_read_msg(NULL, &ivshmem.server.sharedFD))
{ {
DEBUG_ERROR("read unused failed"); DEBUG_ERROR("failed to read shared memory file descriptor");
ivshmem_cleanup(); ivshmem_cleanup();
return false; return false;
} }
if (!ivshmem_read(&init.sharedFD, sizeof(init.sharedFD))) struct stat stat;
if (fstat(ivshmem.server.sharedFD, &stat) != 0)
{ {
DEBUG_ERROR("read shared memory file descriptor failed"); DEBUG_ERROR("failed to stat shared FD");
ivshmem_cleanup(); ivshmem_cleanup();
return false; return false;
} }
DEBUG_PROTO("Protocol : %ld", init.version ); ivshmem.mapSize = stat.st_size;
DEBUG_PROTO("Client ID: %ld", init.clientID);
DEBUG_PROTO("Unused : %ld", init.unused ); DEBUG_INFO("RAM Size : %ld", ivshmem.mapSize);
DEBUG_PROTO("Shared FD: %ld", init.sharedFD); ivshmem.map = mmap(
NULL,
stat.st_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
ivshmem.server.sharedFD,
0);
if (!ivshmem.map)
{
DEBUG_ERROR("failed to map memory");
ivshmem_cleanup();
return false;
}
return true; return true;
} }
@ -102,6 +133,11 @@ bool ivshmem_connect(const char * unix_socket)
void ivshmem_cleanup() void ivshmem_cleanup()
{ {
if (ivshmem.map)
munmap(ivshmem.map, ivshmem.mapSize);
ivshmem.map = NULL;
ivshmem.mapSize = 0;
if (ivshmem.socket >= 0) if (ivshmem.socket >= 0)
{ {
close(ivshmem.socket); close(ivshmem.socket);
@ -143,3 +179,103 @@ bool ivshmem_read(void * buffer, const ssize_t size)
return true; return true;
} }
// ============================================================================
bool ivshmem_read_msg(int64_t * index, int * fd)
{
if (!ivshmem.connected)
{
DEBUG_ERROR("not connected");
return false;
}
struct msghdr msg;
struct iovec iov[1];
union {
struct cmsghdr cmsg;
char control[CMSG_SPACE(sizeof(int))];
} msg_control;
int64_t tmp;
if (!index)
index = &tmp;
iov[0].iov_base = index;
iov[0].iov_len = sizeof(*index);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = &msg_control;
msg.msg_controllen = sizeof(msg_control);
int ret = recvmsg(ivshmem.socket, &msg, 0);
if (ret < sizeof(*index))
{
DEBUG_ERROR("failed ot read message\n");
return false;
}
if (ret == 0)
{
DEBUG_ERROR("lost connetion to server\n");
return false;
}
if (!fd)
return true;
struct cmsghdr *cmsg;
for(cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
{
if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS)
{
continue;
}
memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
}
return true;
}
// ============================================================================
void * ivshmem_get_map()
{
if (!ivshmem.connected)
{
DEBUG_ERROR("not connected");
return NULL;
}
if (!ivshmem.map)
{
DEBUG_ERROR("not mapped");
return NULL;
}
return ivshmem.map;
}
// ============================================================================
size_t ivshmem_get_map_size()
{
if (!ivshmem.connected)
{
DEBUG_ERROR("not connected");
return 0;
}
if (!ivshmem.map)
{
DEBUG_ERROR("not mapped");
return 0;
}
return ivshmem.mapSize;
}

View File

@ -1,13 +1,9 @@
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
struct IVSHMEMInit
{
int64_t version;
int64_t clientID;
int64_t unused;
int64_t sharedFD;
};
bool ivshmem_connect(const char * unix_socket); bool ivshmem_connect(const char * unix_socket);
void ivshmem_close(); void ivshmem_close();
void * ivshmem_get_map();
size_t ivshmem_get_map_size();

Binary file not shown.

View File

@ -1,8 +1,6 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -16,6 +14,7 @@
#define DEBUG #define DEBUG
#include "debug.h" #include "debug.h"
#include "KVMGFXHeader.h" #include "KVMGFXHeader.h"
#include "ivshmem/ivshmem.h"
#include "spice/spice.h" #include "spice/spice.h"
#include "kb.h" #include "kb.h"
@ -470,21 +469,16 @@ int main(int argc, char * argv[])
while(1) while(1)
{ {
umask(0); if (!ivshmem_connect("/tmp/ivshmem_socket"))
const mode_t mode =
S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;
if ((shm_fd = shm_open("ivshmem", O_CREAT | O_RDWR, mode)) < 0)
{ {
DEBUG_ERROR("failed to open shared memory: %d %s", errno, strerror(errno)); DEBUG_ERROR("failed to connect to the ivshmem server");
break; break;
} }
if (ftruncate(shm_fd, MAP_SIZE) != 0) state.shm = (struct KVMGFXHeader *)ivshmem_get_map();
if (!state.shm)
{ {
DEBUG_ERROR("failed to truncate memory region"); DEBUG_ERROR("Failed to map memory");
break; break;
} }
@ -508,13 +502,6 @@ int main(int argc, char * argv[])
break; break;
} }
state.shm = (struct KVMGFXHeader *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (!state.shm)
{
DEBUG_ERROR("Failed to map memory");
break;
}
if (!(t_event = SDL_CreateThread(eventThread, "eventThread", NULL))) if (!(t_event = SDL_CreateThread(eventThread, "eventThread", NULL)))
{ {
DEBUG_ERROR("gpu create thread failed"); DEBUG_ERROR("gpu create thread failed");
@ -541,12 +528,8 @@ int main(int argc, char * argv[])
if (state.window) if (state.window)
SDL_DestroyWindow(state.window); SDL_DestroyWindow(state.window);
if (state.shm)
munmap(state.shm, MAP_SIZE);
if (shm_fd) if (shm_fd)
close(shm_fd); close(shm_fd);
//shm_unlink("kvm-windows");
SDL_Quit(); SDL_Quit();
return 0; return 0;