Esempio n. 1
0
/* Called when headers are complete but body may not be.
 * Request is thus in use from another thread once headers
 * are complete.
 */
static void
hwf_connection_container_on_incoming_message(HioConnection   *connection,
                                             HioIncoming     *incoming)
{
    HrtTask *task;

    g_assert(HWF_IS_REQUEST_CONTAINER(incoming));

    task = hrt_task_create_task(connection->task);

    hrt_debug("Created task %p for incoming request %p",
              task, incoming);

    /* execute the request handler */
    hrt_task_add_immediate(task,
                           on_request_run,
                           g_object_ref(incoming),
                           (GDestroyNotify) g_object_unref);

    /* don't quit the connection task while request tasks are pending */
    hrt_task_add_subtask(connection->task,
                         task,
                         on_request_completed,
                         g_object_ref(incoming),
                         (GDestroyNotify) g_object_unref);

    g_object_unref(task);
}
Esempio n. 2
0
static gboolean
on_server_socket_accepted(HioServer *server,
                          int        fd,
                          void      *data)
{
    HwfContainer *container = HWF_CONTAINER(data);
    HrtTask *task;
    GValue value = { 0, };

    hrt_debug("Creating connection for accepted socket %d", fd);

    task = hrt_task_runner_create_task(container->runner);

    g_value_init(&value, HJS_TYPE_RUNTIME_SPIDERMONKEY);
    g_value_set_object(&value, container->runtime);
    hrt_task_add_arg(task, "runtime", &value);
    g_value_unset(&value);

    hio_connection_process_socket(HWF_TYPE_CONNECTION_CONTAINER,
                                  task,
                                  fd);

    /* task will be ref'd by the watchers added by hwf_connection_process_socket() */
    g_object_unref(task);

    return TRUE;
}
Esempio n. 3
0
static void
hwf_request_container_add_header(HioRequestHttp *http,
                                 HrtBuffer      *name,
                                 HrtBuffer      *value)
{
    /* FIXME */
    hrt_debug("%s", G_STRFUNC);
}
Esempio n. 4
0
/* request has been sufficiently parsed (usually, it has all headers
 * but not the body if any) to go ahead and start working.
 */
void
hwf_request_container_execute(HwfRequestContainer *request,
                              HrtTask             *request_task)
{
    HioResponseHttp *response;
    HrtBuffer *buffer;

    hrt_debug("Executing request %p in task %p", request, request_task);

    response = hio_request_http_get_response(HIO_REQUEST_HTTP(request));

    hio_response_http_send_headers(response);

    buffer = hrt_buffer_new_static_utf8_locked("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"><TITLE>HELLO WORLD</TITLE><P>This is a web page.</P>");

    hio_response_http_write(response, buffer);

    hrt_buffer_unref(buffer);

    hio_response_http_close(response);
}
Esempio n. 5
0
static gboolean
on_request_completed(HrtTask        *task,
                     HrtWatcherFlags flags,
                     void           *data)
{
    HwfRequestContainer *request;
    HioResponseHttp *response;

    request = HWF_REQUEST_CONTAINER(data);

    hrt_debug("Task %p request %p completed",
              task, request);

    /* Automatically send headers and close the body,
     * if it wasn't done already.
     */
    response = hio_request_http_get_response(HIO_REQUEST_HTTP(request));

    hio_response_http_send_headers(response);
    hio_response_http_close(response);

    return FALSE;
}
Esempio n. 6
0
static HioRequestHttp*
hwf_connection_container_create_request(HioConnectionHttp *http,
                                        const char        *method,
                                        int                major_version,
                                        int                minor_version,
                                        const char        *path,
                                        const char        *query_string)
{
    HioRequestHttp *request;
    GValue value = { 0, };

    request = hio_request_http_new(HWF_TYPE_REQUEST_CONTAINER,
                                   method,
                                   major_version, minor_version,
                                   path, query_string);

    g_value_init(&value, HJS_TYPE_RUNTIME);
    if (!hrt_task_get_arg(HIO_CONNECTION(http)->task,
                          "runtime",
                          &value,
                          NULL))
        g_error("Task didn't have a runtime set on it");

    hwf_request_container_set_runtime(HWF_REQUEST_CONTAINER(request),
                                      g_value_get_object(&value));

    g_value_unset(&value);

    hrt_debug("Created request %s %d.%d '%s' query '%s'",
              hio_request_http_get_method(request),
              hio_request_http_get_major_version(request),
              hio_request_http_get_minor_version(request),
              hio_request_http_get_path(request),
              hio_request_http_get_query_string(request));

    return request;
}
Esempio n. 7
0
gboolean
hio_server_listen_tcp(HioServer   *hio_server,
                      const char  *host,
                      int          port,
                      GError     **error)
{
    struct addrinfo hints;
    struct addrinfo *ai_iter;
    struct addrinfo *ai;
    socklen_t addr_len;
    struct sockaddr_storage addr;
    char buf[10];
    int result;
    GIOChannel *io_channel;
    int fd;

    if (g_atomic_int_get(&hio_server->fd) >= 0) {
        g_set_error(error,
                    G_FILE_ERROR,
                    G_FILE_ERROR_FAILED,
                    "Server open already");
        return FALSE;
    }

    memset(&hints, '\0', sizeof(hints));

    hints.ai_family = AF_INET;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; /* AI_NUMERICHOST needed on numeric hosts... */

    snprintf(buf, sizeof(buf), "%d", port);
    buf[sizeof(buf)-1] = '\0';
    ai = NULL;
    result = getaddrinfo(host,
                         &buf[0],
                         &hints,
                         &ai);
    if (result != 0 || ai == NULL) {
        g_set_error(error,
                    G_FILE_ERROR,
                    G_FILE_ERROR_FAILED,
                    "getaddrinfo(): %s",
                    gai_strerror(result));
        return FALSE;
    }

    /* for now we don't listen on multiple, just use first */
    for (ai_iter = ai; ai_iter != NULL; ai_iter = ai_iter->ai_next) {
        fd = socket(ai_iter->ai_family,
                    SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
                    0);
        if (fd < 0) {
            freeaddrinfo(ai);

            g_set_error(error,
                        G_FILE_ERROR,
                        G_FILE_ERROR_FAILED,
                        "socket(): %s",
                        strerror(errno));
            return FALSE;
        }

        if (bind(fd,
                 (struct sockaddr*) ai_iter->ai_addr,
                 ai_iter->ai_addrlen) < 0) {

            freeaddrinfo(ai);
            close(fd);

            g_set_error(error,
                        G_FILE_ERROR,
                        G_FILE_ERROR_FAILED,
                        "bind(): %s",
                        strerror(errno));
            return FALSE;
        }

        if (listen(fd, 75) < 0) {
            freeaddrinfo(ai);
            close(fd);

            g_set_error(error,
                        G_FILE_ERROR,
                        G_FILE_ERROR_FAILED,
                        "listen(): %s",
                        strerror(errno));
            return FALSE;
        }

        break;
    }

    freeaddrinfo(ai);

    addr_len = sizeof(addr);
    result = getsockname(fd,
                         (struct sockaddr*) &addr,
                         &addr_len);
    if (result < 0) {
        g_set_error(error,
                    G_FILE_ERROR,
                    G_FILE_ERROR_FAILED,
                    "getsockname(): %s",
                    strerror(errno));
        close(fd);
        return FALSE;
    }

    if (port == 0) {
        /* see what port we got */
        result = getnameinfo((struct sockaddr*)&addr, addr_len,
                             NULL, 0,
                             buf, sizeof(buf),
                             NI_NUMERICHOST);
        buf[sizeof(buf) - 1] = '\0';
        if (result < 0) {
            g_set_error(error,
                        G_FILE_ERROR,
                        G_FILE_ERROR_FAILED,
                        "getnameinfo(): %s",
                        strerror(errno));
            close(fd);
            return FALSE;
        }

        hio_server->port = atoi(buf);
        if (hio_server->port == 0) {
            g_set_error(error,
                        G_FILE_ERROR,
                        G_FILE_ERROR_FAILED,
                        "invalid port %s",
                        buf);
            close(fd);
            return FALSE;
        }
    } else {
        hio_server->port = port;
    }

    io_channel = g_io_channel_unix_new(fd);
    hio_server->on_new_connections_id = add_io_watch(hio_server->main_context,
                                                     io_channel,
                                                     G_IO_IN,
                                                     on_new_connections,
                                                     hio_server);
    g_io_channel_unref(io_channel);

    g_atomic_int_set(&hio_server->fd, fd);

    hrt_debug("Socket fd %d now open host '%s' port %u",
              fd, host, hio_server->port);

    return TRUE;
}
Esempio n. 8
0
static gboolean
on_new_connections(GIOChannel   *source,
                   GIOCondition  condition,
                   gpointer      data)
{
    HioServer *hio_server = HIO_SERVER(data);
    struct sockaddr addr;
    socklen_t addrlen;
    int client_fd;
    gboolean accepted;

    if (!(condition & G_IO_IN))
        return TRUE;

    addrlen = sizeof(addr);

    /* accept as many things as we can in a loop, this reduces
     * main loop iterations
     */
    while (TRUE) {
        int listen_fd = g_atomic_int_get(&hio_server->fd);
        if (listen_fd < 0) {
            /* socket was closed */
            break;
        }

        client_fd = accept4(listen_fd,
                            &addr, &addrlen, SOCK_CLOEXEC | SOCK_NONBLOCK);

        if (client_fd < 0) {
            if (errno == EINTR) {
                continue;
            } else if (errno == EWOULDBLOCK || errno == EAGAIN) {
                /* nothing else to accept */
                break;
            } else if (errno == EBADF) {
                /* we closed the socket */
                hrt_debug("socket was invalid when we called accept4()");
                break;
            } else {
                hrt_message("accept4(): %s", strerror(errno));
                break;
            }
        }

        hrt_debug("accepted new socket %d", client_fd);

        accepted = FALSE;
        g_signal_emit(G_OBJECT(hio_server),
                      signals[SOCKET_ACCEPTED],
                      0, client_fd, &accepted);
        /* If nobody else has returned true, we just close the new connection. */
        if (!accepted) {
            shutdown(client_fd, SHUT_RDWR);
            close(client_fd);
            hrt_debug("nobody wanted new socket %d so we closed it", client_fd);
        }
    }

    return TRUE;
}