/* IN ANY THREAD */ void hio_output_stream_error(HioOutputStream *stream) { /* incrementing error and closing will make * hio_output_stream_is_done() return TRUE. At that point we need * to be sure done-notification happens if it hasn't. */ g_atomic_int_inc(&stream->errored); /* close to ignore any further writes. we want to * silently eat them, so errors don't have to be handled * by the writer. (Though writer could do so, if desired.) */ hio_output_stream_close(stream); /* Delete any leftover buffers, in our task thread. This would not * work if we were already done-notified because completion would * be unblocked and we can't add watchers to a completed * task. There's no buffers if we're already done, anyhow. */ if (g_atomic_int_get(&stream->done_notified) == 0) { hrt_task_add_immediate(stream->task, on_error_drop_all_buffers, g_object_ref(stream), g_object_unref); } }
void hio_response_http_send_headers(HioResponseHttp *http) { /* FIXME send actual headers */ g_mutex_lock(http->headers_lock); /* Sending headers twice is allowed, for example request handlers * can do it early, but a container might do it automatically * after the request handler runs. Only first send does anything * of course and it's an error to try to set headers after we * already sent them. */ if (http->headers_sent) { g_mutex_unlock(http->headers_lock); return; } http->headers_sent = TRUE; write_to_header(http, "HTTP/1.1 200 OK\r\n"); write_to_header(http, "Date: Wed, 21 Jul 2010 02:24:36 GMT\r\n"); write_to_header(http, "Server: hrt/" VERSION "\r\n"); write_to_header(http, "Last-Modified: Tue, 01 Dec 2009 23:10:05 GMT\r\n"); write_to_header(http, "Content-Type: text/html\r\n"); write_to_header(http, "Connection: close\r\n"); write_to_header(http, "\r\n"); hio_output_stream_close(http->header_stream); g_mutex_unlock(http->headers_lock); }
static gboolean on_write_stream_task(HrtTask *task, HrtWatcherFlags flags, void *data) { WriteTaskData *wtd = data; write_stream(wtd->stream, wtd->desc); hio_output_stream_close(wtd->stream); return FALSE; }
/* IN OUR TASK THREAD */ static gboolean on_ready_to_write(HrtTask *task, HrtWatcherFlags flags, void *data) { HioOutputStream *stream; stream = HIO_OUTPUT_STREAM(data); HRT_ASSERT_IN_TASK_THREAD(stream->task); /* ensure_current_buffer() also does drop_all_buffers() * if an error has occurred to be sure current_buffer * is NULL on error. */ ensure_current_buffer(stream, NULL); if (stream->current_buffer != NULL) { if (hrt_buffer_write(stream->current_buffer, g_atomic_int_get(&stream->fd), &stream->current_buffer_remaining)) { if (stream->current_buffer_remaining == 0) { /* get a new current buffer, deleting this one */ ensure_current_buffer(stream, stream->current_buffer); } } else { /* ERROR */ g_atomic_int_inc(&stream->errored); hio_output_stream_close(stream); drop_all_buffers(stream); } } if (stream->current_buffer == NULL) { /* if no new buffer, we probably need removing. */ check_write_watcher(stream); } notify_if_done(stream); /* stay installed until check_write_watcher() removes us. */ return TRUE; }
void hio_response_http_close(HioResponseHttp *http) { hio_output_stream_close(http->body_stream); }