GDataOutputStream *ekg_connection_add( GSocketConnection *conn, GInputStream *raw_instream, GOutputStream *raw_outstream, ekg_input_callback_t callback, ekg_failure_callback_t failure_callback, gpointer priv_data) { struct ekg_connection *c = g_slice_new(struct ekg_connection); GOutputStream *bout = g_buffered_output_stream_new(raw_outstream); c->conn = conn; c->instream = g_data_input_stream_new(raw_instream); c->outstream = g_data_output_stream_new(bout); c->cancellable = g_cancellable_new(); c->wr_buffer = g_string_new(""); c->callback = callback; c->failure_callback = failure_callback; c->priv_data = priv_data; #if NEED_SLAVERY c->master = get_slave_connection_by_conn(conn); c->slave = NULL; /* be a good slave.. er, servant */ if (G_UNLIKELY(c->master)) { struct ekg_connection *ci; c->master->slave = c; /* shift flush handlers (if set) * this is required in order to be able to easily set flush * handlers for future slaves */ for (ci = c; ci->master && (ci->master->flush_handler != setup_async_write); ci = ci->master) ci->flush_handler = ci->master->flush_handler; ci->flush_handler = setup_async_write; } else #endif c->flush_handler = setup_async_write; /* LF works fine for CRLF */ g_data_input_stream_set_newline_type(c->instream, G_DATA_STREAM_NEWLINE_TYPE_LF); /* disallow any blocking writes */ g_buffered_output_stream_set_auto_grow(G_BUFFERED_OUTPUT_STREAM(bout), TRUE); connections = g_slist_prepend(connections, c); #if NEED_SLAVERY if (G_LIKELY(!c->master)) #endif setup_async_read(c); return c->outstream; }
static gboolean on_incoming_connection(GThreadedSocketService *service, GSocketConnection *connection, GObject *source_object, OwrImageServer *image_server) { GOutputStream *bos; GDataInputStream *dis; gchar *error_body, *error_header = NULL, *response_header = NULL; gchar *line, *tag; gsize line_length, i; guint content_length = 0; OwrImageRenderer *image_renderer; GBytes *image; gconstpointer image_data; gsize image_data_size = 0; OWR_UNUSED(service); OWR_UNUSED(source_object); g_return_val_if_fail(OWR_IS_IMAGE_SERVER(image_server), TRUE); bos = g_buffered_output_stream_new(g_io_stream_get_output_stream(G_IO_STREAM(connection))); dis = g_data_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(connection))); g_data_input_stream_set_newline_type(dis, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); error_body = "404 Not Found"; error_header = g_strdup_printf(HTTP_RESPONSE_HEADER_TEMPLATE, 404, "Not Found", "text/plain", (guint)strlen(error_body)); while (TRUE) { line = g_data_input_stream_read_line(dis, &line_length, NULL, NULL); if (!line) break; if (line_length > 6) { tag = g_strdup(line + 7); for (i = 0; i < strlen(tag); i++) { if (tag[i] == '-') { tag[i] = '\0'; break; } } } else tag = NULL; g_free(line); while ((line = g_data_input_stream_read_line(dis, &line_length, NULL, NULL))) { g_free(line); if (!line_length) { /* got all request headers */ break; } } if (!line) break; g_mutex_lock(&image_server->priv->image_renderers_mutex); image_renderer = tag ? g_hash_table_lookup(image_server->priv->image_renderers, tag) : NULL; g_mutex_unlock(&image_server->priv->image_renderers_mutex); image = image_renderer ? _owr_image_renderer_pull_bmp_image(image_renderer) : NULL; if (!image) { g_output_stream_write(bos, error_header, strlen(error_header), NULL, NULL); g_output_stream_write(bos, error_body, strlen(error_body), NULL, NULL); break; } image_data = g_bytes_get_data(image, &image_data_size); if (content_length != image_data_size) { content_length = image_data_size; g_free(response_header); response_header = g_strdup_printf(HTTP_RESPONSE_HEADER_TEMPLATE, 200, "OK", "image/bmp", content_length); g_buffered_output_stream_set_buffer_size(G_BUFFERED_OUTPUT_STREAM(bos), strlen(response_header) + content_length); } g_output_stream_write(bos, response_header, strlen(response_header), NULL, NULL); g_output_stream_write(bos, image_data, image_data_size, NULL, NULL); g_output_stream_flush(bos, NULL, NULL); g_bytes_unref(image); } g_free(response_header); g_free(error_header); g_object_unref(dis); g_object_unref(bos); return FALSE; }