static int decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg) { struct cmsghdr *cmsg; size_t size, max, i; int overflow = 0; for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) continue; size = cmsg->cmsg_len - CMSG_LEN(0); max = sizeof(buffer->data) - wl_buffer_size(buffer); if (size > max || overflow) { overflow = 1; size /= sizeof(int32_t); for (i = 0; i < size; i++) close(((int*)CMSG_DATA(cmsg))[i]); } else if (wl_buffer_put(buffer, CMSG_DATA(cmsg), size) < 0) { return -1; } } if (overflow) { errno = EOVERFLOW; return -1; } return 0; }
static int wl_connection_put_fd(struct wl_connection *connection, int32_t fd) { if (wl_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) { connection->want_flush = 1; if (wl_connection_flush(connection) < 0) return -1; } return wl_buffer_put(&connection->fds_out, &fd, sizeof fd); }
static int wl_connection_put_fd(struct wl_connection *connection, int32_t fd) { if (wl_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) if (wl_connection_data(connection, WL_CONNECTION_WRITABLE)) return -1; wl_buffer_put(&connection->fds_out, &fd, sizeof fd); return 0; }
void wl_connection_write(struct wl_connection *connection, const void *data, size_t count) { wl_buffer_put(&connection->out, data, count); if (connection->out.head - connection->out.tail == count) connection->update(connection, WL_CONNECTION_READABLE | WL_CONNECTION_WRITABLE, connection->data); }
int wl_connection_queue(struct wl_connection *connection, const void *data, size_t count) { if (connection->out.head - connection->out.tail + count > ARRAY_LENGTH(connection->out.data)) { connection->want_flush = 1; if (wl_connection_flush(connection) < 0) return -1; } return wl_buffer_put(&connection->out, data, count); }
int wl_connection_queue(struct wl_connection *connection, const void *data, size_t count) { if (connection->out.head - connection->out.tail + count > ARRAY_LENGTH(connection->out.data)) if (wl_connection_data(connection, WL_CONNECTION_WRITABLE)) return -1; wl_buffer_put(&connection->out, data, count); return 0; }
static void decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg) { struct cmsghdr *cmsg; size_t size; for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { size = cmsg->cmsg_len - CMSG_LEN(0); wl_buffer_put(buffer, CMSG_DATA(cmsg), size); } } }
int wl_connection_write(struct wl_connection *connection, const void *data, size_t count) { if (connection->out.head - connection->out.tail + count > ARRAY_LENGTH(connection->out.data)) if (wl_connection_data(connection, WL_CONNECTION_WRITABLE)) return -1; wl_buffer_put(&connection->out, data, count); if (!connection->write_signalled) { connection->update(connection, WL_CONNECTION_READABLE | WL_CONNECTION_WRITABLE, connection->data); connection->write_signalled = 1; } return 0; }
struct wl_closure * wl_connection_vmarshal(struct wl_connection *connection, struct wl_object *sender, uint32_t opcode, va_list ap, const struct wl_message *message) { struct wl_closure *closure = &connection->send_closure; struct wl_object **objectp, *object; uint32_t length, *p, *start, size; int dup_fd; struct wl_array **arrayp, *array; const char **sp, *s; char *extra; int i, count, fd, extra_size, *fd_ptr; extra_size = wl_message_size_extra(message); count = strlen(message->signature) + 2; extra = (char *) closure->buffer; start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)]; p = &start[2]; for (i = 2; i < count; i++) { switch (message->signature[i - 2]) { case 'u': closure->types[i] = &ffi_type_uint32; closure->args[i] = p; *p++ = va_arg(ap, uint32_t); break; case 'i': closure->types[i] = &ffi_type_sint32; closure->args[i] = p; *p++ = va_arg(ap, int32_t); break; case 's': closure->types[i] = &ffi_type_pointer; closure->args[i] = extra; sp = (const char **) extra; extra += sizeof *sp; s = va_arg(ap, const char *); length = s ? strlen(s) + 1: 0; *p++ = length; if (length > 0) *sp = (const char *) p; else *sp = NULL; memcpy(p, s, length); p += DIV_ROUNDUP(length, sizeof *p); break; case 'o': closure->types[i] = &ffi_type_pointer; closure->args[i] = extra; objectp = (struct wl_object **) extra; extra += sizeof *objectp; object = va_arg(ap, struct wl_object *); *objectp = object; *p++ = object ? object->id : 0; break; case 'n': closure->types[i] = &ffi_type_uint32; closure->args[i] = p; object = va_arg(ap, struct wl_object *); *p++ = object->id; break; case 'a': closure->types[i] = &ffi_type_pointer; closure->args[i] = extra; arrayp = (struct wl_array **) extra; extra += sizeof *arrayp; *arrayp = (struct wl_array *) extra; extra += sizeof **arrayp; array = va_arg(ap, struct wl_array *); if (array == NULL || array->size == 0) { *p++ = 0; break; } *p++ = array->size; memcpy(p, array->data, array->size); (*arrayp)->size = array->size; (*arrayp)->alloc = array->alloc; (*arrayp)->data = p; p += DIV_ROUNDUP(array->size, sizeof *p); break; case 'h': closure->types[i] = &ffi_type_sint; closure->args[i] = extra; fd_ptr = (int *) extra; extra += sizeof *fd_ptr; fd = va_arg(ap, int); dup_fd = dup(fd); if (dup_fd < 0) { fprintf(stderr, "dup failed: %m"); abort(); } *fd_ptr = dup_fd; wl_buffer_put(&connection->fds_out, &dup_fd, sizeof dup_fd); break; default: assert(0); break; } } size = (p - start) * sizeof *p; start[0] = sender->id; start[1] = opcode | (size << 16); closure->start = start; closure->message = message; closure->count = count; return closure; }