예제 #1
0
 void
 onRequest (Session& session)
 {
     session.write (std::string ("Hello, world!\n"));
     if (is_keep_alive(session.request()))
         session.complete();
     else
         session.close (true);
 }
예제 #2
0
 void testPrepare()
 {
     request_v1<empty_body> m;
     m.version = 10;
     BEAST_EXPECT(! is_upgrade(m));
     m.headers.insert("Transfer-Encoding", "chunked");
     try
     {
         prepare(m);
         fail();
     }
     catch(std::exception const&)
     {
     }
     m.headers.erase("Transfer-Encoding");
     m.headers.insert("Content-Length", "0");
     try
     {
         prepare(m);
         fail();
     }
     catch(std::exception const&)
     {
         pass();
     }
     m.headers.erase("Content-Length");
     m.headers.insert("Connection", "keep-alive");
     try
     {
         prepare(m);
         fail();
     }
     catch(std::exception const&)
     {
         pass();
     }
     m.version = 11;
     m.headers.erase("Connection");
     m.headers.insert("Connection", "close");
     BEAST_EXPECT(! is_keep_alive(m));
 }
예제 #3
0
static void ev_handler(struct ns_connection *nc, int ev, void *ev_data) {
    struct conn_data *conn = (struct conn_data *) nc->user_data;
    const time_t now = time(NULL);
#ifdef DEBUG
    write_log("%d conn=%p nc=%p ev=%d ev_data=%p bec=%p bec_nc=%p\n", now, conn,
              nc, ev, ev_data, conn != NULL ? conn->be_conn : NULL,
              conn != NULL && conn->be_conn != NULL ? conn->be_conn->nc : NULL);
#endif

    if (conn == NULL) {
        if (ev == NS_ACCEPT) {
            conn = calloc(1, sizeof(*conn));
            if (conn == NULL) {
                send_http_err(nc, s_error_500);
            } else {
                memset(conn, 0, sizeof(*conn));
                nc->user_data = conn;
                conn->client.nc = nc;
                conn->client.body_len = -1;
                conn->backend.body_len = -1;
                conn->last_activity = now;
            }
            return;
        } else {
            nc->flags |= NSF_CLOSE_IMMEDIATELY;
            return;
        }
    }

    if (ev != NS_POLL) conn->last_activity = now;

    switch (ev) {
    case NS_HTTP_REQUEST: { /* From client */
        assert(conn != NULL);
        assert(conn->be_conn == NULL);
        struct http_message *hm = (struct http_message *) ev_data;
        conn->client.flags.keep_alive = is_keep_alive(hm);

        if (!connect_backend(conn, hm)) {
            respond_with_error(conn, s_error_500);
            break;
        }

        if (conn->backend.nc == NULL) {
            /* This is a redirect, we're done. */
            conn->client.nc->flags |= NSF_SEND_AND_CLOSE;
            break;
        }

        forward(conn, hm, &conn->client, &conn->backend);
        break;
    }

    case NS_CONNECT: { /* To backend */
        assert(conn != NULL);
        assert(conn->be_conn != NULL);
        int status = *(int *) ev_data;
        if (status != 0) {
            write_log("Error connecting to %s: %d (%s)\n",
                      conn->be_conn->be->host_port, status, strerror(status));
            /* TODO(lsm): mark backend as defunct, try it later on */
            respond_with_error(conn, s_error_500);
            conn->be_conn->nc = NULL;
            release_backend(conn);
            break;
        }
        break;
    }

    case NS_HTTP_REPLY: { /* From backend */
        assert(conn != NULL);
        struct http_message *hm = (struct http_message *) ev_data;
        conn->backend.flags.keep_alive = s_backend_keepalive && is_keep_alive(hm);
        forward(conn, hm, &conn->backend, &conn->client);
        release_backend(conn);
        if (!conn->client.flags.keep_alive) {
            conn->client.nc->flags |= NSF_SEND_AND_CLOSE;
        } else {
#ifdef DEBUG
            write_log("conn=%p remains open\n", conn);
#endif
        }
        break;
    }

    case NS_POLL: {
        assert(conn != NULL);
        if (now - conn->last_activity > CONN_IDLE_TIMEOUT &&
                conn->backend.nc == NULL /* not waiting for backend */) {
#ifdef DEBUG
            write_log("conn=%p has been idle for too long\n", conn);
            conn->client.nc->flags |= NSF_SEND_AND_CLOSE;
#endif
        }
        break;
    }

    case NS_CLOSE: {
        assert(conn != NULL);
        if (nc == conn->client.nc) {
#ifdef DEBUG
            write_log("conn=%p nc=%p client closed, body_sent=%d\n", conn, nc,
                      conn->backend.body_sent);
#endif
            conn->client.nc = NULL;
            if (conn->backend.nc != NULL) {
                conn->backend.nc->flags |= NSF_CLOSE_IMMEDIATELY;
            }
        } else if (nc == conn->backend.nc) {
#ifdef DEBUG
            write_log("conn=%p nc=%p backend closed\n", conn, nc);
#endif
            conn->backend.nc = NULL;
            if (conn->client.nc != NULL &&
                    (conn->backend.body_len < 0 ||
                     conn->backend.body_sent < conn->backend.body_len)) {
                write_log("Backend %s disconnected.\n", conn->be_conn->be->host_port);
                respond_with_error(conn, s_error_500);
            }
        }
        if (conn->client.nc == NULL && conn->backend.nc == NULL) {
            free(conn);
        }
        break;
    }
    }
}