X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ffrontend%2Fconnection.c;h=173bdef475a278d264c999194766f82bbadffe6c;hb=c08c6541795e2ca4da72640a449347d7b708b1dc;hp=aa0325570171c9f6f0807edc92c953ace241004d;hpb=95151b82610bd542d27b5372503f9afffaccd859;p=sysdb.git diff --git a/src/frontend/connection.c b/src/frontend/connection.c index aa03255..173bdef 100644 --- a/src/frontend/connection.c +++ b/src/frontend/connection.c @@ -117,6 +117,7 @@ connection_init(sdb_object_t *obj, va_list ap) conn->cmd = CONNECTION_IDLE; conn->cmd_len = 0; + conn->skip_len = 0; /* update the object name */ snprintf(obj->name + strlen(CONN_FD_PREFIX), @@ -259,20 +260,11 @@ command_handle(sdb_conn_t *conn) int status = -1; assert(conn && (conn->cmd != CONNECTION_IDLE)); + assert(! conn->skip_len); sdb_log(SDB_LOG_DEBUG, "frontend: Handling command %u (len: %u)", conn->cmd, conn->cmd_len); - if ((! conn->username) && (conn->cmd != CONNECTION_STARTUP)) { - const char *errmsg = "Authentication required"; - sdb_connection_send(conn, CONNECTION_ERROR, - (uint32_t)strlen(errmsg), errmsg); - return -1; - } - - /* reset */ - sdb_strbuf_sprintf(conn->errbuf, ""); - switch (conn->cmd) { case CONNECTION_PING: status = sdb_connection_ping(conn); @@ -359,12 +351,6 @@ command_handle(sdb_conn_t *conn) sdb_connection_send(conn, CONNECTION_ERROR, (uint32_t)sdb_strbuf_len(conn->errbuf), sdb_strbuf_string(conn->errbuf)); - - /* remove the command from the buffer */ - if (conn->cmd_len) - sdb_strbuf_skip(conn->buf, 0, conn->cmd_len); - conn->cmd = CONNECTION_IDLE; - conn->cmd_len = 0; return status; } /* command_handle */ @@ -372,17 +358,42 @@ command_handle(sdb_conn_t *conn) static int command_init(sdb_conn_t *conn) { - size_t len; + const char *errmsg = NULL; assert(conn && (conn->cmd == CONNECTION_IDLE) && (! conn->cmd_len)); + if (conn->skip_len) + return -1; + + /* reset */ + sdb_strbuf_sprintf(conn->errbuf, ""); + conn->cmd = connection_get_int32(conn, 0); conn->cmd_len = connection_get_int32(conn, sizeof(uint32_t)); - len = 2 * sizeof(uint32_t); - if (conn->cmd == CONNECTION_IDLE) - len += conn->cmd_len; - sdb_strbuf_skip(conn->buf, 0, len); + sdb_strbuf_skip(conn->buf, 0, 2 * sizeof(uint32_t)); + + if ((! conn->username) && (conn->cmd != CONNECTION_STARTUP)) + errmsg = "Authentication required"; + else if (conn->cmd == CONNECTION_IDLE) + errmsg = "Invalid command 0"; + + if (errmsg) { + size_t len = sdb_strbuf_len(conn->buf); + + sdb_strbuf_sprintf(conn->errbuf, errmsg); + sdb_connection_send(conn, CONNECTION_ERROR, + (uint32_t)strlen(errmsg), errmsg); + conn->skip_len += conn->cmd_len; + conn->cmd = CONNECTION_IDLE; + conn->cmd_len = 0; + + if (len > conn->skip_len) + len = conn->skip_len; + sdb_strbuf_skip(conn->buf, 0, len); + conn->skip_len -= len; + /* connection_read will handle anything else */ + } return 0; } /* command_init */ @@ -411,7 +422,19 @@ connection_read(sdb_conn_t *conn) else if (! status) /* EOF */ break; + if (conn->skip_len) { + size_t len = (size_t)status < conn->skip_len + ? (size_t)status : conn->skip_len; + sdb_strbuf_skip(conn->buf, 0, len); + conn->skip_len -= len; + } + n += status; + + /* give the main loop a chance to execute commands (and free up buffer + * space) on large amounts of incoming traffic */ + if (n > 1024 * 1024) + break; } return n; @@ -468,9 +491,16 @@ sdb_connection_read(sdb_conn_t *conn) && (sdb_strbuf_len(conn->buf) >= 2 * sizeof(int32_t))) command_init(conn); if ((conn->cmd != CONNECTION_IDLE) - && (sdb_strbuf_len(conn->buf) >= conn->cmd_len)) + && (sdb_strbuf_len(conn->buf) >= conn->cmd_len)) { command_handle(conn); + /* remove the command from the buffer */ + if (conn->cmd_len) + sdb_strbuf_skip(conn->buf, 0, conn->cmd_len); + conn->cmd = CONNECTION_IDLE; + conn->cmd_len = 0; + } + if (status <= 0) break;