X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Fclient%2Fsock.c;h=0d734f3a9462ba74bb7405beb94c9fdeecb67d8a;hp=59c77873e08411b22a9c1e5a6a857a8e269210f5;hb=d25f3c59b5cf5387acd4e6d1467ce9efffa40f9a;hpb=3cc3e3c36239c902263678100180c95c8263f7f8 diff --git a/src/client/sock.c b/src/client/sock.c index 59c7787..0d734f3 100644 --- a/src/client/sock.c +++ b/src/client/sock.c @@ -25,13 +25,19 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + #include "client/sock.h" #include "utils/error.h" #include "utils/strbuf.h" #include "utils/proto.h" +#include "utils/os.h" #include +#include #include #include @@ -52,6 +58,7 @@ struct sdb_client { char *address; int fd; + bool eof; }; /* @@ -104,6 +111,7 @@ sdb_client_create(const char *address) } memset(client, 0, sizeof(*client)); client->fd = -1; + client->eof = 1; client->address = strdup(address); if (! client->address) { @@ -154,12 +162,13 @@ sdb_client_connect(sdb_client_t *client, const char *username) if (client->fd < 0) return -1; + client->eof = 0; /* XXX */ if (! username) username = ""; - status = sdb_client_send(client, CONNECTION_STARTUP, + status = sdb_client_send(client, SDB_CONNECTION_STARTUP, (uint32_t)strlen(username), username); if (status < 0) { char errbuf[1024]; @@ -172,22 +181,34 @@ sdb_client_connect(sdb_client_t *client, const char *username) buf = sdb_strbuf_create(64); rstatus = 0; status = sdb_client_recv(client, &rstatus, buf); + if ((status > 0) && (rstatus == SDB_CONNECTION_OK)) { + sdb_strbuf_destroy(buf); + return 0; + } + if (status < 0) { char errbuf[1024]; - sdb_client_close(client); - sdb_strbuf_destroy(buf); sdb_log(SDB_LOG_ERR, "Failed to receive server response: %s", sdb_strerror(errno, errbuf, sizeof(errbuf))); - return (int)status; } - - if (rstatus != CONNECTION_OK) { - sdb_client_close(client); - sdb_strbuf_destroy(buf); - sdb_log(SDB_LOG_ERR, "Access denied for user '%s'", username); - return -((int)rstatus); + else if (client->eof) + sdb_log(SDB_LOG_ERR, "Encountered end-of-file while waiting " + "for server response"); + + if (rstatus == SDB_CONNECTION_ERROR) { + sdb_log(SDB_LOG_ERR, "Access denied for user '%s': %s", + username, sdb_strbuf_string(buf)); + status = -((int)rstatus); + } + else if (rstatus != SDB_CONNECTION_OK) { + sdb_log(SDB_LOG_ERR, "Received unsupported authentication request " + "(status %d) during startup", (int)rstatus); + status = -((int)rstatus); } - return 0; + + sdb_client_close(client); + sdb_strbuf_destroy(buf); + return (int)status; } /* sdb_client_connect */ int @@ -198,6 +219,22 @@ sdb_client_sockfd(sdb_client_t *client) return client->fd; } /* sdb_client_sockfd */ +int +sdb_client_shutdown(sdb_client_t *client, int how) +{ + if (! client) { + errno = ENOTSOCK; + return -1; + } + + if (client->fd < 0) { + errno = EBADF; + return -1; + } + + return shutdown(client->fd, how); +} /* sdb_client_shutdown */ + void sdb_client_close(sdb_client_t *client) { @@ -206,16 +243,21 @@ sdb_client_close(sdb_client_t *client) close(client->fd); client->fd = -1; + client->eof = 1; } /* sdb_client_close */ ssize_t sdb_client_send(sdb_client_t *client, uint32_t cmd, uint32_t msg_len, const char *msg) { + char buf[2 * sizeof(uint32_t) + msg_len]; + if ((! client) || (! client->fd)) return -1; + if (sdb_proto_marshal(buf, sizeof(buf), cmd, msg_len, msg) < 0) + return -1; - return sdb_proto_send_msg(client->fd, cmd, msg_len, msg); + return sdb_write(client->fd, sizeof(buf), buf); } /* sdb_client_send */ ssize_t @@ -241,7 +283,7 @@ sdb_client_recv(sdb_client_t *client, while (42) { ssize_t status; - if (sdb_proto_select(client->fd, SDB_PROTO_SELECTIN)) + if (sdb_select(client->fd, SDB_SELECTIN)) return -1; errno = 0; @@ -251,8 +293,10 @@ sdb_client_recv(sdb_client_t *client, continue; return status; } - else if (! status) /* EOF */ + else if (! status) { + client->eof = 1; break; + } total += (size_t)status; @@ -260,9 +304,15 @@ sdb_client_recv(sdb_client_t *client, continue; if (rstatus == UINT32_MAX) { + const char *str = sdb_strbuf_string(buf) + data_offset; + size_t len = sdb_strbuf_len(buf) - data_offset; + ssize_t n; + /* retrieve status and data len */ - rstatus = sdb_proto_get_int(buf, data_offset); - rlen = sdb_proto_get_int(buf, data_offset + sizeof(rstatus)); + assert(len >= 2 * sizeof(uint32_t)); + n = sdb_proto_unmarshal_int32(str, len, &rstatus); + str += n; len -= (size_t)n; + sdb_proto_unmarshal_int32(str, len, &rlen); if (! rlen) break; @@ -290,5 +340,13 @@ sdb_client_recv(sdb_client_t *client, return (ssize_t)total; } /* sdb_client_recv */ +bool +sdb_client_eof(sdb_client_t *client) +{ + if ((! client) || (client->fd < 0)) + return 1; + return client->eof; +} /* sdb_client_eof */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */