]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: Added a very dummy test-http-server
authorTimo Sirainen <tss@iki.fi>
Thu, 11 Jul 2013 11:29:05 +0000 (14:29 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 11 Jul 2013 11:29:05 +0000 (14:29 +0300)
src/lib-http/Makefile.am
src/lib-http/test-http-server.c [new file with mode: 0644]

index f773b403b8c3223abc72d7ecf1fc6fa7fe04ac00..d0ae216421f0f70ec737f022336ef6b98bc623dd 100644 (file)
@@ -45,7 +45,8 @@ test_programs = \
        test-http-response-parser
 
 test_nocheck_programs = \
-       test-http-client
+       test-http-client \
+       test-http-server
 
 noinst_PROGRAMS = $(test_programs) $(test_nocheck_programs)
 
@@ -103,6 +104,19 @@ test_http_client_DEPENDENCIES = \
        ../lib-ssl-iostream/libssl_iostream.la \
        $(test_deps)
 
+test_http_server_SOURCES = test-http-server.c
+test_http_server_LDFLAGS = -export-dynamic
+test_http_server_LDADD = \
+       libhttp.la \
+       ../lib-dns/libdns.la \
+       ../lib-ssl-iostream/libssl_iostream.la \
+       $(test_libs)
+test_http_server_DEPENDENCIES = \
+       libhttp.la \
+       ../lib-dns/libdns.la \
+       ../lib-ssl-iostream/libssl_iostream.la \
+       $(test_deps)
+
 check: check-am check-test
 check-test: all-am
        for bin in $(test_programs); do \
diff --git a/src/lib-http/test-http-server.c b/src/lib-http/test-http-server.c
new file mode 100644 (file)
index 0000000..c1ccef7
--- /dev/null
@@ -0,0 +1,131 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "ioloop.h"
+#include "ostream.h"
+#include "connection.h"
+#include "http-date.h"
+#include "http-request-parser.h"
+
+static struct connection_list *clients;
+static int fd_listen;
+struct io *io_listen;
+
+struct client {
+       struct connection conn;
+       struct http_request_parser *parser;
+};
+
+static void client_destroy(struct connection *conn)
+{
+       struct client *client = (struct client *)conn;
+
+       http_request_parser_deinit(&client->parser);
+       connection_deinit(&client->conn);
+       i_free(client);
+}
+
+static int
+client_handle_request(struct client *client, struct http_request *request)
+{
+       string_t *str = t_str_new(128);
+
+       if (strcmp(request->method, "GET") != 0) {
+               o_stream_send_str(client->conn.output, "HTTP/1.1 501 Not Implemented\r\nAllow: GET\r\n\r\n");
+               return 0;
+       }
+       str_append(str, "HTTP/1.1 200 OK\r\n");
+       str_printfa(str, "Date: %s\r\n", http_date_create(ioloop_time));
+       str_printfa(str, "Content-Length: %d\r\n", (int)strlen(request->target));
+       str_append(str, "Content-Type: text/plain\r\n");
+       str_append(str, "\r\n");
+       str_append(str, request->target);
+       o_stream_send(client->conn.output, str_data(str), str_len(str));
+       return 0;
+}
+
+static void client_input(struct connection *conn)
+{
+       struct client *client = (struct client *)conn;
+       struct http_request *request;
+       const char *error;
+       int ret;
+
+       while ((ret = http_request_parse_next(client->parser, &request, &error)) > 0) {
+               if (client_handle_request(client, request) < 0 ||
+                   request->connection_close) {
+                       client_destroy(conn);
+                       return;
+               }
+       }
+       if (ret < 0) {
+               i_error("Client sent invalid request: %s", error);
+               client_destroy(conn);
+       }
+}
+
+static struct connection_settings client_set = {
+       .input_max_size = (size_t)-1,
+       .output_max_size = (size_t)-1,
+       .client = FALSE
+};
+
+static const struct connection_vfuncs client_vfuncs = {
+       .destroy = client_destroy,
+       .input = client_input
+};
+
+static void client_init(int fd)
+{
+       struct client *client;
+
+       client = i_new(struct client, 1);
+       connection_init_server(clients, &client->conn,
+                              "(http client)", fd, fd);
+       client->parser = http_request_parser_init(client->conn.input);
+}
+
+static void client_accept(void *context ATTR_UNUSED)
+{
+       int fd;
+
+       fd = net_accept(fd_listen, NULL, NULL);
+       if (fd == -1)
+               return;
+       if (fd == -2)
+               i_fatal("accept() failed: %m");
+
+       client_init(fd);
+}
+
+int main(int argc, char *argv[])
+{
+       struct ip_addr my_ip;
+       struct ioloop *ioloop;
+       unsigned int port;
+
+       lib_init();
+       if (argc < 2 || str_to_uint(argv[1], &port) < 0)
+               i_fatal("Port parameter missing");
+       if (argc < 3)
+               net_get_ip_any4(&my_ip);
+       else if (net_addr2ip(argv[2], &my_ip) < 0)
+               i_fatal("Invalid IP parameter");
+
+       ioloop = io_loop_create();
+       clients = connection_list_init(&client_set, &client_vfuncs);
+
+       fd_listen = net_listen(&my_ip, &port, 128);
+       if (fd_listen == -1)
+               i_fatal("listen(port=%u) failed: %m", port);
+       io_listen = io_add(fd_listen, IO_READ, client_accept, NULL);
+
+       io_loop_run(ioloop);
+
+       io_remove(&io_listen);
+       i_close_fd(&fd_listen);
+       connection_list_deinit(&clients);
+       io_loop_destroy(&ioloop);
+       lib_deinit();
+}