From 2ac970fa16325417a8990c632a3cb9ec85929eef Mon Sep 17 00:00:00 2001 From: Sergey Lyubka <valenok@gmail.com> Date: Sat, 1 Mar 2014 01:17:39 +0000 Subject: [PATCH] Moving to event-based API, temporary breaking tests --- examples/unit_test.c | 36 ++++----- mongoose.c | 185 +++++++++++++++++++------------------------ mongoose.h | 24 +++--- 3 files changed, 109 insertions(+), 136 deletions(-) diff --git a/examples/unit_test.c b/examples/unit_test.c index f5b57d926..6e04248a3 100644 --- a/examples/unit_test.c +++ b/examples/unit_test.c @@ -339,20 +339,17 @@ static const char *test_next_option(void) { return NULL; } -static int cb1(struct mg_connection *conn) { - int result = MG_REQUEST_NOT_PROCESSED; - if (!strcmp(conn->uri, "/cb1")) { +static int evh1(struct mg_connection *conn, enum mg_event ev) { + if (ev == MG_HTTP_ERROR) { + mg_printf(conn, "HTTP/1.0 404 NF\r\n\r\nERR: %d", conn->status_code); + return MG_TRUE; + } else if (ev == MG_REQ_BEGIN && !strcmp(conn->uri, "/cb1")) { mg_printf(conn, "%s %s %s", conn->server_param == NULL ? "?" : (char *) conn->server_param, conn->connection_param == NULL ? "?" : "!", conn->remote_ip); - result = MG_REQUEST_PROCESSED; + return MG_TRUE; } - return result; -} - -static int error_handler(struct mg_connection *conn) { - mg_printf(conn, "HTTP/1.0 404 NF\r\n\r\nERR: %d", conn->status_code); - return MG_ERROR_PROCESSED; + return MG_FALSE; } static int ts1(struct mg_connection *conn) { @@ -379,16 +376,14 @@ static int ts2(struct mg_connection *conn) { static const char *test_server(void) { char buf1[100] = "", buf2[100] = ""; - struct mg_server *server = mg_create_server((void *) "foo"); + struct mg_server *server = mg_create_server((void *) "foo", evh1); ASSERT(server != NULL); ASSERT(mg_set_option(server, "listening_port", LISTENING_ADDR) == NULL); ASSERT(mg_set_option(server, "document_root", ".") == NULL); - mg_set_request_handler(server, cb1); - mg_set_http_error_handler(server, error_handler); - ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, ts1, buf1) == 1); - ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, ts2, buf2) == 1); + ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, buf1) == 1); + ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, buf2) == 1); { int i; for (i = 0; i < 50; i++) mg_poll_server(server, 1); } ASSERT(strcmp(buf1, "foo ? 127.0.0.1") == 0); @@ -464,15 +459,14 @@ static int cb3(struct mg_connection *conn) { static const char *test_mg_connect(void) { char buf2[40] = "", buf3[40] = "", buf4[40] = ""; - struct mg_server *server = mg_create_server(NULL); + struct mg_server *server = mg_create_server(NULL, NULL); // cb4h ASSERT(mg_set_option(server, "listening_port", LISTENING_ADDR) == NULL); ASSERT(mg_set_option(server, "document_root", ".") == NULL); - mg_set_request_handler(server, cb4h); ASSERT(mg_connect(server, "", 0, 0, NULL, NULL) == 0); - ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, cb2, buf2) == 1); + ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, buf2) == 1); ASSERT(mg_connect(server, "127.0.0.1", 29, 0, cb3, buf3) == 1); - ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, cb4, buf4) == 1); + ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, buf4) == 1); { int i; for (i = 0; i < 50; i++) mg_poll_server(server, 1); } @@ -562,7 +556,7 @@ static const char *test_ssl(void) { #endif static const char *test_mg_set_option(void) { - struct mg_server *server = mg_create_server(NULL); + struct mg_server *server = mg_create_server(NULL, NULL); ASSERT(mg_set_option(server, "listening_port", "0") == NULL); ASSERT(mg_get_option(server, "listening_port")[0] != '\0'); mg_destroy_server(&server); @@ -571,7 +565,7 @@ static const char *test_mg_set_option(void) { static const char *test_rewrites(void) { char buf1[100] = "xx"; - struct mg_server *server = mg_create_server(NULL); + struct mg_server *server = mg_create_server(NULL, NULL); ASSERT(mg_set_option(server, "listening_port", "0") == NULL); ASSERT(mg_set_option(server, "document_root", ".") == NULL); diff --git a/mongoose.c b/mongoose.c index a417be80c..fed4145b4 100644 --- a/mongoose.c +++ b/mongoose.c @@ -325,14 +325,14 @@ void *ns_start_thread(void *(*f)(void *), void *p) { } #endif // NS_DISABLE_THREADS -static void add_connection(struct ns_server *server, struct ns_connection *c) { +static void ns_add_conn(struct ns_server *server, struct ns_connection *c) { c->next = server->active_connections; server->active_connections = c; c->prev = NULL; if (c->next != NULL) c->next->prev = c; } -static void remove_connection(struct ns_connection *conn) { +static void ns_remove_conn(struct ns_connection *conn) { if (conn->prev == NULL) conn->server->active_connections = conn->next; if (conn->prev) conn->prev->next = conn->next; if (conn->next) conn->next->prev = conn->prev; @@ -341,7 +341,7 @@ static void remove_connection(struct ns_connection *conn) { // Print message to buffer. If buffer is large enough to hold the message, // return buffer. If buffer is to small, allocate large enough buffer on heap, // and return allocated buffer. -static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap) { +static int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap) { va_list ap_copy; int len; @@ -380,7 +380,7 @@ int ns_vprintf(struct ns_connection *conn, const char *fmt, va_list ap) { char mem[2000], *buf = mem; int len; - if ((len = alloc_vprintf(&buf, sizeof(mem), fmt, ap)) > 0) { + if ((len = ns_avprintf(&buf, sizeof(mem), fmt, ap)) > 0) { iobuf_append(&conn->send_iobuf, buf, len); } if (buf != mem && buf != NULL) { @@ -399,14 +399,14 @@ int ns_printf(struct ns_connection *conn, const char *fmt, ...) { return len; } -static void call_user(struct ns_connection *conn, enum ns_event ev, void *p) { +static void ns_call(struct ns_connection *conn, enum ns_event ev, void *p) { if (conn->server->callback) conn->server->callback(conn, ev, p); } -static void close_conn(struct ns_connection *conn) { +static void ns_close_conn(struct ns_connection *conn) { DBG(("%p %d", conn, conn->flags)); - call_user(conn, NS_CLOSE, NULL); - remove_connection(conn); + ns_call(conn, NS_CLOSE, NULL); + ns_remove_conn(conn); closesocket(conn->sock); iobuf_free(&conn->recv_iobuf); iobuf_free(&conn->send_iobuf); @@ -421,7 +421,7 @@ void ns_set_close_on_exec(sock_t sock) { #endif } -static void set_non_blocking_mode(sock_t sock) { +static void ns_set_non_blocking_mode(sock_t sock) { #ifdef _WIN32 unsigned long on = 1; ioctlsocket(sock, FIONBIO, &on); @@ -467,7 +467,7 @@ int ns_socketpair(sock_t sp[2]) { #endif // NS_DISABLE_SOCKETPAIR // Valid listening port spec is: [ip_address:]port, e.g. "80", "127.0.0.1:3128" -static int parse_port_string(const char *str, union socket_address *sa) { +static int ns_parse_port_string(const char *str, union socket_address *sa) { unsigned int a, b, c, d, port; int len = 0; #ifdef NS_ENABLE_IPV6 @@ -502,7 +502,7 @@ static int parse_port_string(const char *str, union socket_address *sa) { } // 'sa' must be an initialized address to bind to -static sock_t open_listening_socket(union socket_address *sa) { +static sock_t ns_open_listening_socket(union socket_address *sa) { socklen_t len = sizeof(*sa); sock_t on = 1, sock = INVALID_SOCKET; @@ -511,7 +511,7 @@ static sock_t open_listening_socket(union socket_address *sa) { !bind(sock, &sa->sa, sa->sa.sa_family == AF_INET ? sizeof(sa->sin) : sizeof(sa->sa)) && !listen(sock, SOMAXCONN)) { - set_non_blocking_mode(sock); + ns_set_non_blocking_mode(sock); // In case port was set to 0, get the real port number (void) getsockname(sock, &sa->sa, &len); } else if (sock != INVALID_SOCKET) { @@ -541,11 +541,11 @@ int ns_set_ssl_cert(struct ns_server *server, const char *cert) { } int ns_bind(struct ns_server *server, const char *str) { - parse_port_string(str, &server->listening_sa); + ns_parse_port_string(str, &server->listening_sa); if (server->listening_sock != INVALID_SOCKET) { closesocket(server->listening_sock); } - server->listening_sock = open_listening_socket(&server->listening_sa); + server->listening_sock = ns_open_listening_socket(&server->listening_sa); return server->listening_sock == INVALID_SOCKET ? -1 : (int) ntohs(server->listening_sa.sin.sin_port); } @@ -574,13 +574,13 @@ static struct ns_connection *accept_conn(struct ns_server *server) { #endif } else { ns_set_close_on_exec(sock); - set_non_blocking_mode(sock); + ns_set_non_blocking_mode(sock); c->server = server; c->sock = sock; c->flags |= NSF_ACCEPTED; - add_connection(server, c); - call_user(c, NS_ACCEPT, &sa); + ns_add_conn(server, c); + ns_call(c, NS_ACCEPT, &sa); DBG(("%p %d %p %p", c, c->sock, c->ssl, server->ssl_ctx)); } @@ -598,8 +598,8 @@ static int ns_is_error(int n) { } #ifdef NS_ENABLE_HEXDUMP -static void hexdump(const struct ns_connection *conn, const void *buf, - int len, const char *marker) { +static void ns_hexdump(const struct ns_connection *conn, const void *buf, + int len, const char *marker) { const unsigned char *p = (const unsigned char *) buf; char path[500], date[100], ascii[17]; FILE *fp; @@ -641,7 +641,7 @@ static void hexdump(const struct ns_connection *conn, const void *buf, } #endif -static void read_from_socket(struct ns_connection *conn) { +static void ns_read_from_socket(struct ns_connection *conn) { char buf[2048]; int n = 0; @@ -671,7 +671,7 @@ static void read_from_socket(struct ns_connection *conn) { if (ok != 0) { conn->flags |= NSF_CLOSE_IMMEDIATELY; } - call_user(conn, NS_CONNECT, &ok); + ns_call(conn, NS_CONNECT, &ok); return; } @@ -692,7 +692,7 @@ static void read_from_socket(struct ns_connection *conn) { } #ifdef NS_ENABLE_HEXDUMP - hexdump(conn, buf, n, "<-"); + ns_hexdump(conn, buf, n, "<-"); #endif DBG(("%p <- %d bytes [%.*s%s]", @@ -702,11 +702,11 @@ static void read_from_socket(struct ns_connection *conn) { conn->flags |= NSF_CLOSE_IMMEDIATELY; } else if (n > 0) { iobuf_append(&conn->recv_iobuf, buf, n); - call_user(conn, NS_RECV, &n); + ns_call(conn, NS_RECV, &n); } } -static void write_to_socket(struct ns_connection *conn) { +static void ns_write_to_socket(struct ns_connection *conn) { struct iobuf *io = &conn->send_iobuf; int n = 0; @@ -719,7 +719,7 @@ static void write_to_socket(struct ns_connection *conn) { #ifdef NS_ENABLE_HEXDUMP - hexdump(conn, io->buf, n, "->"); + ns_hexdump(conn, io->buf, n, "->"); #endif DBG(("%p -> %d bytes [%.*s%s]", conn, n, io->len < 40 ? io->len : 40, @@ -736,14 +736,14 @@ static void write_to_socket(struct ns_connection *conn) { conn->flags |= NSF_CLOSE_IMMEDIATELY; } - call_user(conn, NS_SEND, NULL); + ns_call(conn, NS_SEND, NULL); } int ns_send(struct ns_connection *conn, const void *buf, int len) { return iobuf_append(&conn->send_iobuf, buf, len); } -static void add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) { +static void ns_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) { if (sock != INVALID_SOCKET) { FD_SET(sock, set); if (*max_fd == INVALID_SOCKET || sock > *max_fd) { @@ -765,19 +765,19 @@ int ns_server_poll(struct ns_server *server, int milli) { FD_ZERO(&read_set); FD_ZERO(&write_set); - add_to_set(server->listening_sock, &read_set, &max_fd); + ns_add_to_set(server->listening_sock, &read_set, &max_fd); for (conn = server->active_connections; conn != NULL; conn = tmp_conn) { tmp_conn = conn->next; - call_user(conn, NS_POLL, ¤t_time); - add_to_set(conn->sock, &read_set, &max_fd); + ns_call(conn, NS_POLL, ¤t_time); + ns_add_to_set(conn->sock, &read_set, &max_fd); if (conn->flags & NSF_CONNECTING) { - add_to_set(conn->sock, &write_set, &max_fd); + ns_add_to_set(conn->sock, &write_set, &max_fd); } if (conn->send_iobuf.len > 0 && !(conn->flags & NSF_BUFFER_BUT_DONT_SEND)) { - add_to_set(conn->sock, &write_set, &max_fd); + ns_add_to_set(conn->sock, &write_set, &max_fd); } else if (conn->flags & NSF_CLOSE_IMMEDIATELY) { - close_conn(conn); + ns_close_conn(conn); } } @@ -786,7 +786,7 @@ int ns_server_poll(struct ns_server *server, int milli) { if (select((int) max_fd + 1, &read_set, &write_set, NULL, &tv) > 0) { // Accept new connections - if (server->listening_sock >= 0 && + if (server->listening_sock != INVALID_SOCKET && FD_ISSET(server->listening_sock, &read_set)) { // We're not looping here, and accepting just one connection at // a time. The reason is that eCos does not respect non-blocking @@ -800,14 +800,14 @@ int ns_server_poll(struct ns_server *server, int milli) { tmp_conn = conn->next; if (FD_ISSET(conn->sock, &read_set)) { conn->last_io_time = current_time; - read_from_socket(conn); + ns_read_from_socket(conn); } if (FD_ISSET(conn->sock, &write_set)) { if (conn->flags & NSF_CONNECTING) { - read_from_socket(conn); + ns_read_from_socket(conn); } else if (!(conn->flags & NSF_BUFFER_BUT_DONT_SEND)) { conn->last_io_time = current_time; - write_to_socket(conn); + ns_write_to_socket(conn); } } } @@ -817,7 +817,7 @@ int ns_server_poll(struct ns_server *server, int milli) { tmp_conn = conn->next; num_active_connections++; if (conn->flags & NSF_CLOSE_IMMEDIATELY) { - close_conn(conn); + ns_close_conn(conn); } } //DBG(("%d active connections", num_active_connections)); @@ -846,7 +846,7 @@ struct ns_connection *ns_connect(struct ns_server *server, const char *host, sin.sin_family = AF_INET; sin.sin_port = htons((uint16_t) port); sin.sin_addr = * (struct in_addr *) he->h_addr_list[0]; - set_non_blocking_mode(sock); + ns_set_non_blocking_mode(sock); connect_ret_val = connect(sock, (struct sockaddr *) &sin, sizeof(sin)); if (ns_is_error(connect_ret_val)) { @@ -871,7 +871,7 @@ struct ns_connection *ns_connect(struct ns_server *server, const char *host, } #endif - add_connection(server, conn); + ns_add_conn(server, conn); DBG(("%p %s:%d %d %p", conn, host, port, conn->sock, conn->ssl)); return conn; @@ -881,12 +881,12 @@ struct ns_connection *ns_add_sock(struct ns_server *s, sock_t sock, void *p) { struct ns_connection *conn; if ((conn = (struct ns_connection *) NS_MALLOC(sizeof(*conn))) != NULL) { memset(conn, 0, sizeof(*conn)); - set_non_blocking_mode(sock); + ns_set_non_blocking_mode(sock); conn->sock = sock; conn->connection_data = p; conn->server = s; conn->last_io_time = time(NULL); - add_connection(s, conn); + ns_add_conn(s, conn); DBG(("%p %d", conn, sock)); } return conn; @@ -935,7 +935,7 @@ void ns_server_free(struct ns_server *s) { for (conn = s->active_connections; conn != NULL; conn = tmp_conn) { tmp_conn = conn->next; - close_conn(conn); + ns_close_conn(conn); } #ifndef NS_DISABLE_SOCKETPAIR @@ -1122,10 +1122,7 @@ static const char *static_config_options[] = { struct mg_server { struct ns_server ns_server; union socket_address lsa; // Listening socket address - mg_handler_t request_handler; - mg_handler_t http_close_handler; - mg_handler_t error_handler; - mg_handler_t auth_handler; + mg_handler_t event_handler; char *config_options[NUM_OPTIONS]; char local_ip[48]; }; @@ -1155,7 +1152,7 @@ struct connection { int64_t cl; // Reply content length, for Range support int request_len; // Request length, including last \r\n after last header //int flags; // CONN_* flags: CONN_CLOSE, CONN_SPOOL_DONE, etc - mg_handler_t handler; // Callback for HTTP client + //mg_handler_t handler; // Callback for HTTP client }; #define MG_CONN_2_CONN(c) ((struct connection *) ((char *) (c) - \ @@ -1433,6 +1430,12 @@ static const char *status_code_to_str(int status_code) { } } +static int call_user(struct connection *conn, enum mg_event ev) { + return conn != NULL && conn->server != NULL && + conn->server->event_handler != NULL ? + conn->server->event_handler(&conn->mg_conn, ev) : MG_FALSE; +} + static void send_http_error(struct connection *conn, int code, const char *fmt, ...) { const char *message = status_code_to_str(code); @@ -1445,8 +1448,7 @@ static void send_http_error(struct connection *conn, int code, conn->mg_conn.status_code = code; // Invoke error handler if it is set - if (conn->server->error_handler != NULL && - conn->server->error_handler(&conn->mg_conn) == MG_ERROR_PROCESSED) { + if (call_user(conn, MG_HTTP_ERROR) == MG_TRUE) { close_local_endpoint(conn); return; } @@ -2505,7 +2507,7 @@ static int deliver_websocket_frame(struct connection *conn) { } // Call the handler and remove frame from the iobuf - if (conn->server->request_handler(&conn->mg_conn) == MG_CLIENT_CLOSE) { + if (call_user(conn, MG_REQ_BEGIN) == MG_FALSE) { conn->ns_conn->flags |= NSF_FINISHED_SENDING_DATA; } iobuf_remove(&conn->ns_conn->recv_iobuf, frame_len); @@ -2581,15 +2583,11 @@ static void write_terminating_chunk(struct connection *conn) { static int call_request_handler(struct connection *conn) { int result; conn->mg_conn.content = conn->ns_conn->recv_iobuf.buf; - switch ((result = conn->server->request_handler(&conn->mg_conn))) { - case MG_REQUEST_CALL_AGAIN: conn->ns_conn->flags |= MG_LONG_RUNNING; break; - case MG_REQUEST_NOT_PROCESSED: break; - default: - if (conn->ns_conn->flags & MG_HEADERS_SENT) { - write_terminating_chunk(conn); - } - close_local_endpoint(conn); - break; + if ((result = call_user(conn, MG_REQ_BEGIN)) == MG_TRUE) { + if (conn->ns_conn->flags & MG_HEADERS_SENT) { + write_terminating_chunk(conn); + } + close_local_endpoint(conn); } return result; } @@ -3554,8 +3552,7 @@ static int check_password(const char *method, const char *ha1, const char *uri, mg_md5(expected_response, ha1, ":", nonce, ":", nc, ":", cnonce, ":", qop, ":", ha2, NULL); - return mg_strcasecmp(response, expected_response) == 0 ? - MG_AUTH_OK : MG_AUTH_FAIL; + return mg_strcasecmp(response, expected_response) == 0 ? MG_TRUE : MG_FALSE; } @@ -3585,14 +3582,14 @@ int mg_authorize_digest(struct mg_connection *c, FILE *fp) { return check_password(c->request_method, ha1, uri, nonce, nc, cnonce, qop, resp); } - return MG_AUTH_FAIL; + return MG_FALSE; } // Return 1 if request is authorised, 0 otherwise. static int is_authorized(struct connection *conn, const char *path) { FILE *fp; - int authorized = MG_AUTH_OK; + int authorized = MG_TRUE; if ((fp = open_auth_file(conn, path)) != NULL) { authorized = mg_authorize_digest(&conn->mg_conn, fp); @@ -3605,7 +3602,7 @@ static int is_authorized(struct connection *conn, const char *path) { static int is_authorized_for_dav(struct connection *conn) { const char *auth_file = conn->server->config_options[DAV_AUTH_FILE]; FILE *fp; - int authorized = MG_AUTH_FAIL; + int authorized = MG_FALSE; if (auth_file != NULL && (fp = fopen(auth_file, "r")) != NULL) { authorized = mg_authorize_digest(&conn->mg_conn, fp); @@ -3952,16 +3949,14 @@ static void open_local_endpoint(struct connection *conn, int skip_user) { #endif #ifndef MONGOOSE_NO_AUTH - // Call auth handler - if (conn->server->auth_handler != NULL && - conn->server->auth_handler(&conn->mg_conn) == MG_AUTH_FAIL) { + if (conn->server->event_handler && call_user(conn, MG_AUTH) == MG_FALSE) { mg_send_digest_auth_request(&conn->mg_conn); return; } #endif // Call URI handler if one is registered for this URI - if (skip_user == 0 && conn->server->request_handler != NULL) { + if (skip_user == 0 && conn->server->event_handler != NULL) { conn->endpoint_type = EP_USER; #if MONGOOSE_POST_SIZE_LIMIT > 1 { @@ -4130,7 +4125,7 @@ static void call_http_client_handler(struct connection *conn, int code) { conn->mg_conn.content_len = conn->ns_conn->recv_iobuf.len; } conn->mg_conn.content = conn->ns_conn->recv_iobuf.buf; - if (conn->handler(&conn->mg_conn) || code == MG_CONNECT_FAILURE || + if (call_user(conn, -1) || code == MG_CONNECT_FAILURE || code == MG_DOWNLOAD_FAILURE) { conn->ns_conn->flags |= NSF_CLOSE_IMMEDIATELY; } @@ -4156,12 +4151,12 @@ static void process_response(struct connection *conn) { } } -int mg_connect(struct mg_server *server, const char *host, int port, - int use_ssl, mg_handler_t handler, void *param) { +struct mg_connection *mg_connect(struct mg_server *server, const char *host, + int port, int use_ssl) { struct ns_connection *nsconn; struct connection *conn; - nsconn = ns_connect(&server->ns_server, host, port, use_ssl, param); + nsconn = ns_connect(&server->ns_server, host, port, use_ssl, NULL); if (nsconn == NULL) return 0; if ((conn = (struct connection *) calloc(1, sizeof(*conn))) == NULL) { @@ -4175,14 +4170,13 @@ int mg_connect(struct mg_server *server, const char *host, int port, conn->server = server; conn->endpoint_type = EP_CLIENT; - conn->handler = handler; + //conn->handler = handler; conn->mg_conn.server_param = server->ns_server.server_data; - conn->mg_conn.connection_param = param; conn->birth_time = time(NULL); conn->ns_conn->flags = NSF_CONNECTING; conn->mg_conn.status_code = MG_CONNECT_FAILURE; - return 1; + return &conn->mg_conn; } #ifndef MONGOOSE_NO_LOGGING @@ -4311,21 +4305,20 @@ struct mg_iterator { mg_handler_t cb; void *param; }; +union variant { mg_handler_t cb; void *p; }; static void iter(struct ns_connection *nsconn, enum ns_event ev, void *param) { if (ev == NS_POLL) { - struct mg_iterator *it = (struct mg_iterator *) param; + union variant *variant = (union variant *) param; struct connection *c = (struct connection *) nsconn->connection_data; - c->mg_conn.callback_param = it->param; - it->cb(&c->mg_conn); + variant->cb(&c->mg_conn, MG_POLL); } } // Apply function to all active connections. -void mg_iterate_over_connections(struct mg_server *server, mg_handler_t handler, - void *param) { - struct mg_iterator it = { handler, param }; - ns_iterate(&server->ns_server, iter, &it); +void mg_iterate_over_connections(struct mg_server *server, mg_handler_t cb) { + union variant variant = { cb }; + ns_iterate(&server->ns_server, iter, &variant); } static int get_var(const char *data, size_t data_len, const char *name, @@ -4550,7 +4543,7 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) { int ok = * (int *) p; conn->mg_conn.status_code = ok == 0 ? MG_CONNECT_SUCCESS : MG_CONNECT_FAILURE; - if (conn->handler(&conn->mg_conn) != 0 || ok != 0) { + if (call_user(conn, MG_CONNECT) != 0 || ok != 0) { nc->flags |= NSF_CLOSE_IMMEDIATELY; } } @@ -4585,10 +4578,7 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) { call_http_client_handler(conn, MG_DOWNLOAD_SUCCESS); } - if (conn->server->http_close_handler) { - conn->server->http_close_handler(&conn->mg_conn); - } - + call_user(conn, MG_CLOSE); close_local_endpoint(conn); free(conn); } @@ -4619,22 +4609,6 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) { } } -void mg_set_request_handler(struct mg_server *server, mg_handler_t handler) { - server->request_handler = handler; -} - -void mg_set_http_close_handler(struct mg_server *server, mg_handler_t handler) { - server->http_close_handler = handler; -} - -void mg_set_http_error_handler(struct mg_server *server, mg_handler_t handler) { - server->error_handler = handler; -} - -void mg_set_auth_handler(struct mg_server *server, mg_handler_t handler) { - server->auth_handler = handler; -} - void mg_set_listening_socket(struct mg_server *server, int sock) { if (server->ns_server.listening_sock != INVALID_SOCKET) { closesocket(server->ns_server.listening_sock); @@ -4652,9 +4626,10 @@ const char *mg_get_option(const struct mg_server *server, const char *name) { return i == -1 ? NULL : opts[i] == NULL ? "" : opts[i]; } -struct mg_server *mg_create_server(void *server_data) { +struct mg_server *mg_create_server(void *server_data, mg_handler_t handler) { struct mg_server *server = (struct mg_server *) calloc(1, sizeof(*server)); ns_server_init(&server->ns_server, server_data, mg_ev_handler); set_default_option_values(server->config_options); + server->event_handler = handler; return server; } diff --git a/mongoose.h b/mongoose.h index 5748a906a..4426cac6f 100644 --- a/mongoose.h +++ b/mongoose.h @@ -55,26 +55,31 @@ struct mg_connection { int wsbits; // First byte of the websocket frame void *server_param; // Parameter passed to mg_add_uri_handler() void *connection_param; // Placeholder for connection-specific data - void *callback_param; // Used by mg_iterate_over_connections() }; struct mg_server; // Opaque structure describing server instance -typedef int (*mg_handler_t)(struct mg_connection *); +enum mg_result { MG_FALSE, MG_TRUE }; +enum mg_event { + MG_POLL, // Callback return value is ignored + MG_AUTH, // If callback returns MG_FALSE, authentication fails + MG_REQ_BEGIN, // If callback returns MG_FALSE, Mongoose continues with req + MG_REQ_END, // Callback return value is ignored + MG_CLOSE, // Connection is closed + MG_CONNECT, // If callback returns MG_FALSE, connect fails + MG_HTTP_ERROR // If callback returns MG_FALSE, Mongoose continues with err +}; +typedef int (*mg_handler_t)(struct mg_connection *, enum mg_event); // Server management functions -struct mg_server *mg_create_server(void *server_param); +struct mg_server *mg_create_server(void *server_param, mg_handler_t handler); void mg_destroy_server(struct mg_server **); const char *mg_set_option(struct mg_server *, const char *opt, const char *val); int mg_poll_server(struct mg_server *, int milliseconds); -void mg_set_request_handler(struct mg_server *, mg_handler_t); -void mg_set_http_close_handler(struct mg_server *, mg_handler_t); -void mg_set_http_error_handler(struct mg_server *, mg_handler_t); -void mg_set_auth_handler(struct mg_server *, mg_handler_t); const char **mg_get_valid_option_names(void); const char *mg_get_option(const struct mg_server *server, const char *name); void mg_set_listening_socket(struct mg_server *, int sock); int mg_get_listening_socket(struct mg_server *); -void mg_iterate_over_connections(struct mg_server *, mg_handler_t, void *); +void mg_iterate_over_connections(struct mg_server *, mg_handler_t); // Connection management functions void mg_send_status(struct mg_connection *, int status_code); @@ -115,8 +120,7 @@ enum { MG_CONNECT_SUCCESS, MG_CONNECT_FAILURE, MG_DOWNLOAD_SUCCESS, MG_DOWNLOAD_FAILURE }; -int mg_connect(struct mg_server *, const char *host, int port, int use_ssl, - mg_handler_t handler, void *param); +struct mg_connection *mg_connect(struct mg_server *, const char *, int, int); #ifdef __cplusplus } -- GitLab