X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ffrontend%2Fconnection.c;h=6b785392a1255311d5fae116a1bfb334186534db;hb=8e7384947ee57bbbe58e210be4f6ec04ef8ff508;hp=4ba12dcdd568cf0449c45de60b3984607e5ce17d;hpb=ac07692583601db96dc0a655158e78a1cbbbfcfd;p=sysdb.git diff --git a/src/frontend/connection.c b/src/frontend/connection.c index 4ba12dc..6b78539 100644 --- a/src/frontend/connection.c +++ b/src/frontend/connection.c @@ -29,6 +29,7 @@ #include "core/object.h" #include "core/plugin.h" #include "frontend/connection-private.h" +#include "frontend/parser.h" #include "utils/error.h" #include "utils/strbuf.h" #include "utils/proto.h" @@ -139,11 +140,15 @@ connection_destroy(sdb_object_t *obj) "(%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); + sdb_log(SDB_LOG_DEBUG, "frontend: Closing connection %s", obj->name); + if (conn->fd >= 0) + close(conn->fd); conn->fd = -1; + if (conn->username) + free(conn->username); + conn->username = NULL; + sdb_strbuf_destroy(conn->buf); conn->buf = NULL; sdb_strbuf_destroy(conn->errbuf); @@ -183,7 +188,13 @@ sdb_conn_ctx_init(void) static void sdb_conn_set_ctx(sdb_conn_t *conn) { + sdb_conn_t *old; + sdb_conn_ctx_init(); + + old = pthread_getspecific(conn_ctx_key); + if (old) + sdb_object_deref(SDB_OBJ(old)); if (conn) sdb_object_ref(SDB_OBJ(conn)); pthread_setspecific(conn_ctx_key, conn); @@ -206,7 +217,7 @@ sdb_conn_get_ctx(void) * Send a log message originating from the current thread to the client. */ static int -connection_log(int __attribute__((unused)) prio, const char *msg, +connection_log(int prio, const char *msg, sdb_object_t __attribute__((unused)) *user_data) { sdb_conn_t *conn; @@ -217,6 +228,10 @@ connection_log(int __attribute__((unused)) prio, const char *msg, if ((! conn) || (! conn->username)) return 0; + /* XXX: make the log-level configurable by the client at runtime */ + if (prio >= SDB_LOG_DEBUG) + return 0; + /* TODO: Use CONNECTION_LOG_? */ if (sdb_connection_send(conn, CONNECTION_LOG, (uint32_t)strlen(msg), msg) < 0) @@ -252,6 +267,10 @@ command_handle(sdb_conn_t *conn) const char *errmsg = "Authentication required"; sdb_connection_send(conn, CONNECTION_ERROR, (uint32_t)strlen(errmsg), errmsg); + + /* remove the command from the buffer */ + if (conn->cmd_len) + sdb_strbuf_skip(conn->buf, 0, conn->cmd_len); return -1; } @@ -297,16 +316,38 @@ command_handle(sdb_conn_t *conn) node = SDB_CONN_NODE(sdb_llist_get(parsetree, 0)); } - if (node) + if (node) { status = sdb_fe_exec(conn, node); + sdb_object_deref(SDB_OBJ(node)); + } sdb_llist_destroy(parsetree); break; } + case CONNECTION_FETCH: + status = sdb_fe_fetch(conn, sdb_strbuf_string(conn->buf)); + break; case CONNECTION_LIST: status = sdb_fe_list(conn); break; + case CONNECTION_LOOKUP: + { + sdb_store_matcher_t *m; + + m = sdb_fe_parse_matcher(sdb_strbuf_string(conn->buf), + (int)conn->cmd_len); + if (! m) { + sdb_log(SDB_LOG_ERR, "frontend: Failed to parse expression '%s'", + sdb_strbuf_string(conn->buf)); + status = -1; + break; + } + + status = sdb_fe_lookup(conn, m); + sdb_object_deref(SDB_OBJ(m)); + break; + } default: { @@ -355,6 +396,9 @@ connection_read(sdb_conn_t *conn) { ssize_t n = 0; + if ((! conn) || (conn->fd < 0)) + return -1; + while (42) { ssize_t status; @@ -363,6 +407,9 @@ connection_read(sdb_conn_t *conn) if (status < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) break; + + close(conn->fd); + conn->fd = -1; return (int)status; } else if (! status) /* EOF */ @@ -400,6 +447,14 @@ sdb_connection_accept(int fd) void sdb_connection_close(sdb_conn_t *conn) { + if (! conn) + return; + + /* close the connection even if someone else still references it */ + if (conn->fd >= 0) + close(conn->fd); + conn->fd = -1; + sdb_object_deref(SDB_OBJ(conn)); } /* sdb_connection_close */ @@ -443,6 +498,11 @@ sdb_connection_send(sdb_conn_t *conn, uint32_t code, if (status < 0) { char errbuf[1024]; + /* tell other code that there was a problem and, more importantly, + * make sure we don't try to send further logs to the connection */ + close(conn->fd); + conn->fd = -1; + sdb_log(SDB_LOG_ERR, "frontend: Failed to send msg " "(code: %u, len: %u) to client: %s", code, msg_len, sdb_strerror(errno, errbuf, sizeof(errbuf)));