ShmPipe * sp_client_open (const char *path) { ShmPipe *self = spalloc_new (ShmPipe); struct sockaddr_un sun; memset (self, 0, sizeof (ShmPipe)); self->main_socket = socket (PF_UNIX, SOCK_STREAM, 0); if (self->main_socket < 0) { sp_close (self); return NULL; } sun.sun_family = AF_UNIX; strncpy (sun.sun_path, path, sizeof (sun.sun_path) - 1); if (connect (self->main_socket, (struct sockaddr *) &sun, sizeof (struct sockaddr_un)) < 0) goto error; return self; error: spalloc_free (ShmPipe, self); return NULL; }
ShmPipe * sp_client_open (const char *path) { ShmPipe *self = spalloc_new (ShmPipe); struct sockaddr_un sock_un; int flags; memset (self, 0, sizeof (ShmPipe)); self->main_socket = socket (PF_UNIX, SOCK_STREAM, 0); self->use_count = 1; if (self->main_socket < 0) goto error; flags = fcntl (self->main_socket, F_GETFL, 0); if (flags < 0) goto error; if (fcntl (self->main_socket, F_SETFL, flags | FD_CLOEXEC) < 0) goto error; sock_un.sun_family = AF_UNIX; strncpy (sock_un.sun_path, path, sizeof (sock_un.sun_path) - 1); if (connect (self->main_socket, (struct sockaddr *) &sock_un, sizeof (struct sockaddr_un)) < 0) goto error; return self; error: sp_client_close (self); return NULL; }
ShmPipe * sp_writer_create (const char *path, size_t size, mode_t perms) { ShmPipe *self = spalloc_new (ShmPipe); int flags; struct sockaddr_un sun; int i = 0; memset (self, 0, sizeof (ShmPipe)); self->main_socket = socket (PF_UNIX, SOCK_STREAM, 0); if (self->main_socket < 0) { RETURN_ERROR ("Could not create socket (%d): %s\n", errno, strerror (errno)); } flags = fcntl (self->main_socket, F_GETFL, 0); if (flags < 0) { RETURN_ERROR ("fcntl(F_GETFL) failed (%d): %s\n", errno, strerror (errno)); } if (fcntl (self->main_socket, F_SETFL, flags | O_NONBLOCK | FD_CLOEXEC) < 0) { RETURN_ERROR ("fcntl(F_SETFL) failed (%d): %s\n", errno, strerror (errno)); } sun.sun_family = AF_UNIX; strncpy (sun.sun_path, path, sizeof (sun.sun_path) - 1); while (bind (self->main_socket, (struct sockaddr *) &sun, sizeof (struct sockaddr_un)) < 0) { if (errno != EADDRINUSE) RETURN_ERROR ("bind() failed (%d): %s\n", errno, strerror (errno)); if (i > 256) RETURN_ERROR ("Could not find a free socket name for %s", path); snprintf (sun.sun_path, sizeof (sun.sun_path), "%s.%d", path, i); i++; } self->socket_path = strdup (sun.sun_path); if (listen (self->main_socket, 10) < 0) { RETURN_ERROR ("listen() failed (%d): %s\n", errno, strerror (errno)); } self->shm_area = sp_open_shm (NULL, ++self->next_area_id, 1, perms, size); self->perms = perms; if (!self->shm_area) { sp_close (self); return NULL; } return self; }
ShmBlock * sp_writer_alloc_block (ShmPipe * self, size_t size) { ShmBlock *block; ShmAllocBlock *ablock = shm_alloc_space_alloc_block (self->shm_area->allocspace, size); if (!ablock) return NULL; block = spalloc_new (ShmBlock); sp_shm_area_inc (self->shm_area); block->pipe = self; block->area = self->shm_area; block->ablock = ablock; return block; }
ShmClient * sp_writer_accept_client (ShmPipe * self) { ShmClient *client = NULL; int fd; struct CommandBuffer cb = { 0 }; int pathlen = strlen (self->shm_area->shm_area_name) + 1; fd = accept (self->main_socket, NULL, NULL); if (fd < 0) { fprintf (stderr, "Could not client connection"); return NULL; } cb.payload.new_shm_area.size = self->shm_area->shm_area_len; cb.payload.new_shm_area.path_size = pathlen; if (!send_command (fd, &cb, COMMAND_NEW_SHM_AREA, self->shm_area->id)) { fprintf (stderr, "Sending new shm area failed: %s", strerror (errno)); goto error; } if (send (fd, self->shm_area->shm_area_name, pathlen, MSG_NOSIGNAL) != pathlen) { fprintf (stderr, "Sending new shm area path failed: %s", strerror (errno)); goto error; } client = spalloc_new (ShmClient); client->fd = fd; /* Prepend ot linked list */ client->next = self->clients; self->clients = client; self->num_clients++; return client; error: shutdown (fd, SHUT_RDWR); close (fd); return NULL; }
static ShmArea * sp_open_shm (char *path, int id, int writer, mode_t perms, size_t size) { ShmArea *area = spalloc_new (ShmArea); char tmppath[PATH_MAX]; int flags; int prot; int i = 0; memset (area, 0, sizeof (ShmArea)); area->use_count = 1; area->shm_area_len = size; if (writer) flags = O_RDWR | O_CREAT | O_TRUNC | O_EXCL; else flags = O_RDONLY; area->shm_fd = -1; if (path) { area->shm_fd = shm_open (path, flags, perms); } else { do { snprintf (tmppath, PATH_MAX, "/shmpipe.5%d.%5d", getpid (), i++); area->shm_fd = shm_open (tmppath, flags, perms); } while (area->shm_fd < 0 && errno == EEXIST); } if (area->shm_fd < 0) { RETURN_ERROR ("shm_open failed on %s (%d): %s\n", path ? path : tmppath, errno, strerror (errno)); } if (!path) area->shm_area_name = strdup (tmppath); if (writer) { if (ftruncate (area->shm_fd, size)) { RETURN_ERROR ("Could not resize memory area to header size," " ftruncate failed (%d): %s\n", errno, strerror (errno)); } } if (writer) prot = PROT_READ | PROT_WRITE; else prot = PROT_READ; area->shm_area = mmap (NULL, size, prot, MAP_SHARED, area->shm_fd, 0); if (area->shm_area == MAP_FAILED) { RETURN_ERROR ("mmap failed (%d): %s\n", errno, strerror (errno)); } area->id = id; if (writer) area->allocspace = shm_alloc_space_new (area->shm_area_len); return area; }