From: Sebastian Harl Date: Tue, 26 Nov 2013 17:42:58 +0000 (+0100) Subject: frontend: Moved all connection handling operations into connection.c. X-Git-Tag: sysdb-0.1.0~336^2~8 X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=commitdiff_plain;h=5bed28501c56d1268d49e62d807897d2ce32af3f frontend: Moved all connection handling operations into connection.c. connection_obj_t was merged into sdb_conn_t which now inherits from sdb_object_t. The connection object is now private to the library and defined in the new header file connection-private.h. --- diff --git a/src/Makefile.am b/src/Makefile.am index 32c493e..948d1fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,6 +27,7 @@ libsysdb_la_SOURCES = \ include/core/data.h \ core/error.c include/core/error.h \ frontend/connection.c include/frontend/connection.h \ + include/frontend/connection-private.h \ frontend/sock.c include/frontend/sock.h \ frontend/session.c \ utils/channel.c include/utils/channel.h \ diff --git a/src/frontend/connection.c b/src/frontend/connection.c index 90361fe..eb0ada7 100644 --- a/src/frontend/connection.c +++ b/src/frontend/connection.c @@ -27,16 +27,115 @@ #include "sysdb.h" #include "core/error.h" -#include "frontend/connection.h" +#include "core/object.h" +#include "frontend/connection-private.h" #include "utils/strbuf.h" #include #include #include +#include #include +/* + * private data types + */ + +/* name of connection objects */ +#define CONN_FD_PREFIX "conn#" +#define CONN_FD_PLACEHOLDER "XXXXXXX" + +static int +connection_init(sdb_object_t *obj, va_list ap) +{ + sdb_conn_t *conn; + int sock_fd; + int sock_fl; + + assert(obj); + conn = CONN(obj); + + sock_fd = va_arg(ap, int); + + conn->buf = sdb_strbuf_create(/* size = */ 128); + if (! conn->buf) { + sdb_log(SDB_LOG_ERR, "frontend: Failed to allocate a read buffer " + "for a new connection"); + return -1; + } + + conn->client_addr_len = sizeof(conn->client_addr); + conn->fd = accept(sock_fd, (struct sockaddr *)&conn->client_addr, + &conn->client_addr_len); + + if (conn->fd < 0) { + char buf[1024]; + sdb_log(SDB_LOG_ERR, "frontend: Failed to accept remote " + "connection: %s", sdb_strerror(errno, + buf, sizeof(buf))); + return -1; + } + + if (conn->client_addr.ss_family != AF_UNIX) { + sdb_log(SDB_LOG_ERR, "frontend: Accepted connection using " + "unexpected family type %d", conn->client_addr.ss_family); + return -1; + } + + sock_fl = fcntl(conn->fd, F_GETFL); + if (fcntl(conn->fd, F_SETFL, sock_fl | O_NONBLOCK)) { + char buf[1024]; + sdb_log(SDB_LOG_ERR, "frontend: Failed to switch connection conn#%i " + "to non-blocking mode: %s", conn->fd, + sdb_strerror(errno, buf, sizeof(buf))); + return -1; + } + + sdb_log(SDB_LOG_DEBUG, "frontend: Accepted connection on fd=%i", + conn->fd); + + conn->cmd = CONNECTION_IDLE; + conn->cmd_len = 0; + + /* update the object name */ + snprintf(obj->name + strlen(CONN_FD_PREFIX), + strlen(CONN_FD_PLACEHOLDER), "%i", conn->fd); + return 0; +} /* connection_init */ + +static void +connection_destroy(sdb_object_t *obj) +{ + sdb_conn_t *conn; + size_t len; + + assert(obj); + conn = CONN(obj); + + if (conn->buf) { + len = sdb_strbuf_len(conn->buf); + if (len) + sdb_log(SDB_LOG_INFO, "frontend: Discarding incomplete command " + "(%zu byte%s left in buffer)", len, len == 1 ? "" : "s"); + } + + sdb_log(SDB_LOG_DEBUG, "frontend: Closing connection on fd=%i", + conn->fd); + close(conn->fd); + conn->fd = -1; + + sdb_strbuf_destroy(conn->buf); + conn->buf = NULL; +} /* connection_destroy */ + +static sdb_type_t connection_type = { + /* size = */ sizeof(sdb_conn_t), + /* init = */ connection_init, + /* destroy = */ connection_destroy, +}; + /* * connection handler functions */ @@ -139,49 +238,23 @@ connection_read(sdb_conn_t *conn) * public API */ -int -sdb_connection_init(sdb_conn_t *conn) +sdb_conn_t * +sdb_connection_accept(int fd) { - if (conn->buf) { - sdb_log(SDB_LOG_WARNING, "frontend: Attempted to re-initialize " - "a frontend connection"); - return -1; - } - - conn->buf = sdb_strbuf_create(/* size = */ 128); - if (! conn->buf) { - sdb_log(SDB_LOG_ERR, "frontend: Failed to allocate a read buffer " - "for a new connection"); - sdb_connection_close(conn); - return -1; - } + if (fd < 0) + return NULL; - conn->cmd = CONNECTION_IDLE; - conn->cmd_len = 0; - conn->fd = -1; - return 0; -} /* sdb_connection_init */ + /* the placeholder will be replaced with the accepted file + * descriptor when initializing the object */ + return CONN(sdb_object_create(CONN_FD_PREFIX CONN_FD_PLACEHOLDER, + connection_type, fd)); +} /* sdb_connection_create */ void sdb_connection_close(sdb_conn_t *conn) { - size_t len; - - if (conn->buf) { - len = sdb_strbuf_len(conn->buf); - if (len) - sdb_log(SDB_LOG_INFO, "frontend: Discarding incomplete command " - "(%zu byte%s left in buffer)", len, len == 1 ? "" : "s"); - } - - sdb_log(SDB_LOG_DEBUG, "frontend: Closing connection on fd=%i", - conn->fd); - close(conn->fd); - conn->fd = -1; - - sdb_strbuf_destroy(conn->buf); - conn->buf = NULL; -} /* sdb_connection_fini */ + sdb_object_deref(SDB_OBJ(conn)); +} /* sdb_connection_close */ ssize_t sdb_connection_read(sdb_conn_t *conn) diff --git a/src/frontend/session.c b/src/frontend/session.c index b1e527a..9dedcf6 100644 --- a/src/frontend/session.c +++ b/src/frontend/session.c @@ -27,7 +27,7 @@ #include "sysdb.h" -#include "frontend/connection.h" +#include "frontend/connection-private.h" /* * public API diff --git a/src/frontend/sock.c b/src/frontend/sock.c index 1b80efe..cac49e1 100644 --- a/src/frontend/sock.c +++ b/src/frontend/sock.c @@ -28,7 +28,7 @@ #include "sysdb.h" #include "core/error.h" #include "core/object.h" -#include "frontend/connection.h" +#include "frontend/connection-private.h" #include "frontend/sock.h" #include "utils/channel.h" @@ -44,8 +44,6 @@ #include -#include - #include #include #include @@ -54,25 +52,10 @@ #include -/* name of connection objects */ -#define CONN_FD_PREFIX "conn#" -#define CONN_FD_PLACEHOLDER "XXXXXXX" - /* * private data types */ -typedef struct { - sdb_object_t super; - - /* connection and client information */ - struct sockaddr_storage client_addr; - socklen_t client_addr_len; - - sdb_conn_t conn; -} connection_obj_t; -#define CONN(obj) ((connection_obj_t *)(obj)) - typedef struct { char *address; int type; @@ -275,74 +258,6 @@ socket_close(sdb_fe_socket_t *sock) listener_close(sock->listeners + i); } /* socket_close */ -/* - * private data types - */ - -static int -connection_init(sdb_object_t *obj, va_list ap) -{ - connection_obj_t *conn; - int sock_fd; - int sock_fl; - - assert(obj); - conn = CONN(obj); - - sock_fd = va_arg(ap, int); - - if (sdb_connection_init(&CONN(obj)->conn)) - return -1; - - conn->client_addr_len = sizeof(conn->client_addr); - conn->conn.fd = accept(sock_fd, (struct sockaddr *)&conn->client_addr, - &conn->client_addr_len); - - if (conn->conn.fd < 0) { - char buf[1024]; - sdb_log(SDB_LOG_ERR, "frontend: Failed to accept remote " - "connection: %s", sdb_strerror(errno, - buf, sizeof(buf))); - return -1; - } - - if (conn->client_addr.ss_family != AF_UNIX) { - sdb_log(SDB_LOG_ERR, "frontend: Accepted connection using " - "unexpected family type %d", conn->client_addr.ss_family); - return -1; - } - - sock_fl = fcntl(conn->conn.fd, F_GETFL); - if (fcntl(conn->conn.fd, F_SETFL, sock_fl | O_NONBLOCK)) { - char buf[1024]; - sdb_log(SDB_LOG_ERR, "frontend: Failed to switch connection conn#%i " - "to non-blocking mode: %s", conn->conn.fd, - sdb_strerror(errno, buf, sizeof(buf))); - return -1; - } - - sdb_log(SDB_LOG_DEBUG, "frontend: Accepted connection on fd=%i", - conn->conn.fd); - - /* update the object name */ - snprintf(obj->name + strlen(CONN_FD_PREFIX), - strlen(CONN_FD_PLACEHOLDER), "%i", conn->conn.fd); - return 0; -} /* connection_init */ - -static void -connection_destroy(sdb_object_t *obj) -{ - assert(obj); - sdb_connection_close(&CONN(obj)->conn); -} /* connection_destroy */ - -static sdb_type_t connection_type = { - /* size = */ sizeof(connection_obj_t), - /* init = */ connection_init, - /* destroy = */ connection_destroy, -}; - /* * connection handler functions */ @@ -356,7 +271,7 @@ connection_handler(void *data) while (42) { struct timespec timeout = { 0, 500000000 }; /* .5 seconds */ - connection_obj_t *conn; + sdb_conn_t *conn; int status; errno = 0; @@ -375,7 +290,7 @@ connection_handler(void *data) continue; } - status = (int)sdb_connection_read(&conn->conn); + status = (int)sdb_connection_read(conn); if (status <= 0) { /* error or EOF -> close connection */ sdb_object_deref(SDB_OBJ(conn)); @@ -399,25 +314,21 @@ static int connection_accept(sdb_fe_socket_t *sock, listener_t *listener) { sdb_object_t *obj; + int status; - /* the placeholder will be replaced with the accepted file - * descriptor when initializing the object */ - obj = sdb_object_create(CONN_FD_PREFIX CONN_FD_PLACEHOLDER, - connection_type, listener->sock_fd); + obj = SDB_OBJ(sdb_connection_accept(listener->sock_fd)); if (! obj) return -1; - if (sdb_llist_append(sock->open_connections, obj)) { + status = sdb_llist_append(sock->open_connections, obj); + if (status) sdb_log(SDB_LOG_ERR, "frontend: Failed to append " "connection %s to list of open connections", obj->name); - sdb_object_deref(obj); - return -1; - } - /* hand ownership over to the list */ + /* hand ownership over to the list; or destroy in case of an error */ sdb_object_deref(obj); - return 0; + return status; } /* connection_accept */ static int @@ -444,11 +355,11 @@ socket_handle_incoming(sdb_fe_socket_t *sock, while (sdb_llist_iter_has_next(iter)) { sdb_object_t *obj = sdb_llist_iter_get_next(iter); - if (FD_ISSET(CONN(obj)->conn.fd, exceptions)) + if (FD_ISSET(CONN(obj)->fd, exceptions)) sdb_log(SDB_LOG_INFO, "Exception on fd %d", - CONN(obj)->conn.fd); + CONN(obj)->fd); - if (FD_ISSET(CONN(obj)->conn.fd, ready)) { + if (FD_ISSET(CONN(obj)->fd, ready)) { sdb_llist_iter_remove_current(iter); sdb_channel_write(sock->chan, &obj); } @@ -539,7 +450,7 @@ sdb_fe_sock_listen_and_serve(sdb_fe_socket_t *sock, sdb_fe_loop_t *loop) max_listen_fd = listener->sock_fd; } - sock->chan = sdb_channel_create(1024, sizeof(connection_obj_t *)); + sock->chan = sdb_channel_create(1024, sizeof(sdb_conn_t *)); if (! sock->chan) { socket_close(sock); return -1; @@ -574,11 +485,11 @@ sdb_fe_sock_listen_and_serve(sdb_fe_socket_t *sock, sdb_fe_loop_t *loop) while (sdb_llist_iter_has_next(iter)) { sdb_object_t *obj = sdb_llist_iter_get_next(iter); - FD_SET(CONN(obj)->conn.fd, &ready); - FD_SET(CONN(obj)->conn.fd, &exceptions); + FD_SET(CONN(obj)->fd, &ready); + FD_SET(CONN(obj)->fd, &exceptions); - if (CONN(obj)->conn.fd > max_fd) - max_fd = CONN(obj)->conn.fd; + if (CONN(obj)->fd > max_fd) + max_fd = CONN(obj)->fd; } sdb_llist_iter_destroy(iter); diff --git a/src/include/frontend/connection-private.h b/src/include/frontend/connection-private.h new file mode 100644 index 0000000..d484a08 --- /dev/null +++ b/src/include/frontend/connection-private.h @@ -0,0 +1,75 @@ +/* + * SysDB - src/include/frontend/connection-private.h + * Copyright (C) 2013 Sebastian 'tokkee' Harl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * private data structures used by frontend modules + */ + +#ifndef SDB_FRONTEND_CONNECTION_PRIVATE_H +#define SDB_FRONTEND_CONNECTION_PRIVATE_H 1 + +#include "core/object.h" +#include "utils/strbuf.h" +#include "frontend/connection.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sdb_conn { + sdb_object_t super; + + /* file-descriptor of the open connection */ + int fd; + + /* connection and client information */ + struct sockaddr_storage client_addr; + socklen_t client_addr_len; + + /* read buffer */ + sdb_strbuf_t *buf; + + /* connection / protocol state information */ + uint32_t cmd; + uint32_t cmd_len; + + /* user information */ + char *username; /* NULL if the user has not been authenticated */ +}; +#define CONN(obj) ((sdb_conn_t *)(obj)) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ! SDB_FRONTEND_CONNECTION_H */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + diff --git a/src/include/frontend/connection.h b/src/include/frontend/connection.h index a5ea092..141248f 100644 --- a/src/include/frontend/connection.h +++ b/src/include/frontend/connection.h @@ -49,38 +49,24 @@ typedef enum { CONNECTION_STARTUP, } sdb_conn_state_t; -/* a generic connection object */ -typedef struct { - /* file-descriptor of the open connection */ - int fd; - - /* read buffer */ - sdb_strbuf_t *buf; - - /* connection / protocol state information */ - uint32_t cmd; - uint32_t cmd_len; - - /* user information */ - char *username; /* NULL if the user has not been authenticated */ -} sdb_conn_t; +typedef struct sdb_conn sdb_conn_t; /* - * sdb_connection_init: - * Initialize an (already allocated) connection. This function allocates and - * initialized any attributes. It's an error to call init on an already - * initialized object. + * sdb_connection_accpet: + * Accept a new connection on the specified file-descriptor 'fd' and return a + * newly allocated connection object. * * Returns: * - 0 on success * - a negative value else */ -int -sdb_connection_init(sdb_conn_t *conn); +sdb_conn_t * +sdb_connection_accept(int fd); /* * sdb_connection_close: - * Close a open connection and deallocate any memory used by its attributes. + * Close a open connection and deallocate any memory. The connection object is + * no longer valid after calling this function. */ void sdb_connection_close(sdb_conn_t *conn);