static void on_web_socket_message (WebSocketConnection *connection, WebSocketDataType type, GBytes *message, CockpitWebService *self) { CockpitSocket *socket; GBytes *payload; gchar *channel; socket = cockpit_socket_lookup_by_connection (&self->sockets, connection); g_return_if_fail (socket != NULL); payload = cockpit_transport_parse_frame (message, &channel); if (!payload) return; /* A control channel command */ if (!channel) { dispatch_inbound_command (self, socket, payload); } /* An actual payload message */ else if (!self->closing) { if (!self->sent_done) cockpit_transport_send (self->transport, channel, payload); } g_free (channel); g_bytes_unref (payload); }
static void on_pipe_read (CockpitPipe *pipe, GByteArray *input, gboolean end_of_data, gpointer user_data) { CockpitPipeTransport *self = COCKPIT_PIPE_TRANSPORT (user_data); GBytes *message; GBytes *payload; gchar *channel; guint32 size; for (;;) { if (input->len < sizeof (size)) { if (!end_of_data) g_debug ("%s: want more data", self->name); break; } memcpy (&size, input->data, sizeof (size)); size = GUINT32_FROM_BE (size); if (input->len < size + sizeof (size)) { g_debug ("%s: want more data", self->name); break; } message = cockpit_pipe_consume (input, sizeof (size), size); payload = cockpit_transport_parse_frame (message, &channel); if (payload) { g_debug ("%s: received a %d byte payload", self->name, (int)size); cockpit_transport_emit_recv ((CockpitTransport *)self, channel, payload); g_bytes_unref (payload); g_free (channel); } g_bytes_unref (message); } if (end_of_data) { /* Received a partial message */ if (input->len > 0) { g_warning ("%s: received truncated %d byte frame", self->name, input->len); cockpit_pipe_close (pipe, "internal-error"); } } }
static void drain_buffer (CockpitSshTransport *self) { GBytes *message; GBytes *payload; gchar *channel; guint32 size; for (;;) { if (self->buffer->len < sizeof (size)) { if (!self->received_eof) g_debug ("%s: want len have %d", self->logname, (int)self->buffer->len); break; } memcpy (&size, self->buffer->data, sizeof (size)); size = GUINT32_FROM_BE (size); if (self->buffer->len < size + sizeof (size)) { g_debug ("%s: want %d have %d", self->logname, (int)(size + sizeof (size)), (int)self->buffer->len); break; } message = cockpit_pipe_consume (self->buffer, sizeof (size), size, 0); payload = cockpit_transport_parse_frame (message, &channel); if (payload) { g_debug ("%s: received a %d byte payload", self->logname, (int)g_bytes_get_size (payload)); cockpit_transport_emit_recv ((CockpitTransport *)self, channel, payload); g_bytes_unref (payload); g_free (channel); } g_bytes_unref (message); } if (self->received_eof) { /* Received a partial message */ if (self->buffer->len > 0) { g_warning ("%s: received truncated %d byte frame", self->logname, (int)self->buffer->len); close_immediately (self, "internal-error"); } } }
static JsonObject * read_control_message (int fd) { JsonObject *options = NULL; GBytes *payload = NULL; GBytes *bytes = NULL; gchar *channel = NULL; guchar *data = NULL; gssize length = 0; length = cockpit_frame_read (fd, &data); if (length < 0) { g_message ("couldn't read askpass authorize message: %s", g_strerror (errno)); length = 0; } else if (length > 0) { /* This could have a password, so clear it when freeing */ bytes = g_bytes_new_with_free_func (data, length, byte_array_clear_and_free, g_byte_array_new_take (data, length)); payload = cockpit_transport_parse_frame (bytes, &channel); data = NULL; } if (payload == NULL) { if (length > 0) g_message ("askpass did not receive valid message"); } else if (channel != NULL) { g_message ("askpass did not receive a control message"); } else if (!cockpit_transport_parse_command (payload, NULL, NULL, &options)) { g_message ("askpass did not receive a valid control message"); } g_free (channel); if (bytes) g_bytes_unref (bytes); if (payload) g_bytes_unref (payload); free (data); return options; }
static void on_pipe_read (CockpitPipe *pipe, GByteArray *input, gboolean end_of_data, gpointer user_data) { CockpitInteractTransport *self = COCKPIT_INTERACT_TRANSPORT (user_data); GBytes *message; GBytes *payload; gchar *channel; guint8 *pos; guint32 size; for (;;) { pos = NULL; if (input->len > 0) pos = (guint8 *)g_strstr_len ((gchar *)input->data, input->len, self->delimiter); if (!pos) { if (!end_of_data) g_debug ("%s: want more data", self->name); break; } size = pos - input->data; message = cockpit_pipe_consume (input, 0, size, self->delimiter_len); payload = cockpit_transport_parse_frame (message, &channel); if (payload) { g_debug ("%s: received a %d byte payload", self->name, (int)size); cockpit_transport_emit_recv ((CockpitTransport *)self, channel, payload); g_bytes_unref (payload); g_free (channel); } g_bytes_unref (message); } }
/** * cockpit_transport_read_from_pipe: * * Meant to be used in a "read" handler for a #CockpitPipe * Closed is pointer to a boolean value that may be updated * during the read and parse loop. */ void cockpit_transport_read_from_pipe (CockpitTransport *self, const gchar *logname, CockpitPipe *pipe, gboolean *closed, GByteArray *input, gboolean end_of_data) { GBytes *message; GBytes *payload; gchar *channel; guint32 i, size; gchar *data; /* This may be updated during the loop. */ g_assert (closed != NULL); g_object_ref (self); while (!*closed) { size = 0; data = (gchar *)input->data; for (i = 0; i < input->len; i++) { /* Check invalid characters, prevent integer overflow, limit max length */ if (i > 7 || data[i] < '0' || data[i] > '9') break; size *= 10; size += data[i] - '0'; } if (i == input->len) { if (!end_of_data) g_debug ("%s: want more data", logname); break; } if (data[i] != '\n') { g_warning ("%s: incorrect protocol: received invalid length prefix", logname); cockpit_pipe_close (pipe, "protocol-error"); break; } if (input->len < i + 1 + size) { g_debug ("%s: want more data 2", logname); break; } message = cockpit_pipe_consume (input, i + 1, size, 0); payload = cockpit_transport_parse_frame (message, &channel); if (payload) { g_debug ("%s: received a %d byte payload", logname, (int)size); cockpit_transport_emit_recv (self, channel, payload); g_bytes_unref (payload); g_free (channel); } g_bytes_unref (message); } if (end_of_data) { /* Received a partial message */ if (input->len > 0) { g_debug ("%s: received truncated %d byte frame", logname, input->len); cockpit_pipe_close (pipe, "disconnected"); } } g_object_unref (self); }
static void on_pipe_read (CockpitPipe *pipe, GByteArray *input, gboolean end_of_data, gpointer user_data) { CockpitPipeTransport *self = COCKPIT_PIPE_TRANSPORT (user_data); GBytes *message; GBytes *payload; gchar *channel; guint32 i, size; gchar *data; g_object_ref (self); for (;;) { size = 0; data = (gchar *)input->data; for (i = 0; i < input->len; i++) { /* Check invalid characters, prevent integer overflow, limit max length */ if (i > 7 || data[i] < '0' || data[i] > '9') break; size *= 10; size += data[i] - '0'; } if (i == input->len) { if (!end_of_data) g_debug ("%s: want more data", self->name); break; } if (data[i] != '\n') { g_warning ("%s: incorrect protocol: received invalid length prefix", self->name); cockpit_pipe_close (pipe, "protocol-error"); break; } if (input->len < i + 1 + size) { g_debug ("%s: want more data 2", self->name); break; } message = cockpit_pipe_consume (input, i + 1, size, 0); payload = cockpit_transport_parse_frame (message, &channel); if (payload) { g_debug ("%s: received a %d byte payload", self->name, (int)size); cockpit_transport_emit_recv ((CockpitTransport *)self, channel, payload); g_bytes_unref (payload); g_free (channel); } g_bytes_unref (message); } if (end_of_data) { /* Received a partial message */ if (input->len > 0) { g_debug ("%s: received truncated %d byte frame", self->name, input->len); cockpit_pipe_close (pipe, "disconnected"); } } g_object_unref (self); }