diff --git a/src/client/sock.c b/src/client/sock.c
index a2417ad6d872029e8c80f51d83899b65e9026a06..0d734f3a9462ba74bb7405beb94c9fdeecb67d8a 100644 (file)
--- a/src/client/sock.c
+++ b/src/client/sock.c
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
* 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 "client/sock.h"
#include "utils/error.h"
#include "utils/strbuf.h"
#include "utils/proto.h"
+#include "utils/os.h"
#include <arpa/inet.h>
#include <arpa/inet.h>
+#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <errno.h>
#include <limits.h>
struct sdb_client {
char *address;
int fd;
struct sdb_client {
char *address;
int fd;
+ bool eof;
};
/*
};
/*
}
memset(client, 0, sizeof(*client));
client->fd = -1;
}
memset(client, 0, sizeof(*client));
client->fd = -1;
+ client->eof = 1;
client->address = strdup(address);
if (! client->address) {
client->address = strdup(address);
if (! client->address) {
if (client->fd < 0)
return -1;
if (client->fd < 0)
return -1;
+ client->eof = 0;
/* XXX */
if (! username)
username = "";
/* 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];
(uint32_t)strlen(username), username);
if (status < 0) {
char errbuf[1024];
buf = sdb_strbuf_create(64);
rstatus = 0;
status = sdb_client_recv(client, &rstatus, buf);
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];
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)));
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);
}
}
- return 0;
+ else if (rstatus != SDB_CONNECTION_OK) {
+ sdb_log(SDB_LOG_ERR, "Received unsupported authentication request "
+ "(status %d) during startup", (int)rstatus);
+ status = -((int)rstatus);
+ }
+
+ sdb_client_close(client);
+ sdb_strbuf_destroy(buf);
+ return (int)status;
} /* sdb_client_connect */
} /* sdb_client_connect */
+int
+sdb_client_sockfd(sdb_client_t *client)
+{
+ if (! client)
+ return -1;
+ 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)
{
void
sdb_client_close(sdb_client_t *client)
{
close(client->fd);
client->fd = -1;
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)
{
} /* 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 ((! 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
} /* sdb_client_send */
ssize_t
size_t data_offset = sdb_strbuf_len(buf);
size_t data_offset = sdb_strbuf_len(buf);
+ if (code)
+ *code = UINT32_MAX;
+
if ((! client) || (! client->fd) || (! buf)) {
errno = EBADF;
return -1;
}
if ((! client) || (! client->fd) || (! buf)) {
errno = EBADF;
return -1;
}
- if (code)
- *code = UINT32_MAX;
-
while (42) {
ssize_t status;
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;
return -1;
errno = 0;
continue;
return status;
}
continue;
return status;
}
- else if (! status) /* EOF */
+ else if (! status) {
+ client->eof = 1;
break;
break;
+ }
total += (size_t)status;
total += (size_t)status;
continue;
if (rstatus == UINT32_MAX) {
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 */
/* 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;
if (! rlen)
break;
return (ssize_t)total;
} /* sdb_client_recv */
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 : */
/* vim: set tw=78 sw=4 ts=4 noexpandtab : */