[PATCH] [0/1] libmongo-client: add support for Unix sockets
Greetings! This is patch agains the master branch of syslog-ng-3.4. It's more of a proof-of-concept thing, but in a quick session I put support for Unix sockets into libmongo-client. It may not be stunningly beautiful, but I actually used it (along with a second patch, which I will send shortly) to have syslog-ng write to mongodb via a Unix socket. I realize libmongo-client is also on GitHub, but the submodule pointed to a different repo, so I decided to just dump this here. :) If you have any interest at all, I could also clean this up some more. Maybe split across two commits, too. Let me know. Conrad Hoffmann (1): Add support for Unix sockets. examples/mongo-dump.c | 22 +++++++++++++++++----- src/mongo-client.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/mongo-client.h | 12 ++++++++++++ src/mongo-sync.c | 23 +++++++++++++++++++++++ src/mongo-sync.h | 15 +++++++++++++++ 5 files changed, 107 insertions(+), 5 deletions(-) -- 1.7.11.4
Add a separate connect function to both mongo-client and mongo-sync and demonstrate usage by adding this feature to the mongo-dump example program. Replica sets have no support for Unix sockets so far. Signed-off-by: Conrad Hoffmann <ch@bitfehler.net> --- examples/mongo-dump.c | 22 +++++++++++++++++----- src/mongo-client.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/mongo-client.h | 12 ++++++++++++ src/mongo-sync.c | 23 +++++++++++++++++++++++ src/mongo-sync.h | 15 +++++++++++++++ 5 files changed, 107 insertions(+), 5 deletions(-) diff --git a/examples/mongo-dump.c b/examples/mongo-dump.c index d0fe04a..ec666f6 100644 --- a/examples/mongo-dump.c +++ b/examples/mongo-dump.c @@ -29,6 +29,7 @@ typedef struct { gchar *host; gint port; + gchar *path; gchar *db; gchar *coll; gchar *output; @@ -53,10 +54,19 @@ mongo_dump (config_t *config) gchar *error = NULL; int e; - VLOG ("Connecting to %s:%d/%s.%s...\n", config->host, config->port, - config->db, config->coll); + if (config->path) + { + VLOG ("Connecting to %s/%s.%s...\n", config->path,config->db, + config->coll); + conn = mongo_sync_unix_connect (config->path, config->slaveok); + } + else + { + VLOG ("Connecting to %s:%d/%s.%s...\n", config->host, config->port, + config->db, config->coll); + conn = mongo_sync_connect (config->host, config->port, config->slaveok); + } - conn = mongo_sync_connect (config->host, config->port, config->slaveok); if (!conn) { e = errno; @@ -156,7 +166,7 @@ main (int argc, char *argv[]) GError *error = NULL; GOptionContext *context; config_t config = { - NULL, 27017, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE + NULL, 27017, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE }; GOptionEntry entries[] = @@ -164,6 +174,8 @@ main (int argc, char *argv[]) { "host", 'h', 0, G_OPTION_ARG_STRING, &config.host, "Host to connect to", "HOST" }, { "port", 'p', 0, G_OPTION_ARG_INT, &config.port, "Port", "PORT" }, + { "path", 'P', 0, G_OPTION_ARG_STRING, &config.path, + "Path of Unix socket to connect to", "PATH" }, { "db", 'd', 0, G_OPTION_ARG_STRING, &config.db, "Database", "DB" }, { "collection", 'c', 0, G_OPTION_ARG_STRING, &config.coll, "Collection", "COLL" }, @@ -186,7 +198,7 @@ main (int argc, char *argv[]) exit (1); } - if (!config.host || !config.port || !config.db || + if (!((config.host && config.port) || config.path) || !config.db || !config.coll || !config.output) { gchar **nargv; diff --git a/src/mongo-client.c b/src/mongo-client.c index ed931e4..67f9b64 100644 --- a/src/mongo-client.c +++ b/src/mongo-client.c @@ -29,6 +29,7 @@ #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> +#include <sys/un.h> #include <netdb.h> #include <sys/uio.h> #include <netinet/in.h> @@ -109,6 +110,45 @@ mongo_connect (const char *host, int port) return conn; } +mongo_connection * +mongo_unix_connect (const char *path) +{ + int len, fd = -1; + mongo_connection *conn; + struct sockaddr_un remote; + + if (!path) + { + errno = EINVAL; + return NULL; + } + + conn = g_new0 (mongo_connection, 1); + + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + errno = EADDRNOTAVAIL; + return NULL; + } + + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, path); + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + if (connect(fd, (struct sockaddr *)&remote, len) == -1) + { + close(fd); + g_free (conn); + + errno = EADDRNOTAVAIL; + return NULL; + } + + conn->fd = fd; + + return conn; +} + void mongo_disconnect (mongo_connection *conn) { diff --git a/src/mongo-client.h b/src/mongo-client.h index 28863e5..3917b05 100644 --- a/src/mongo-client.h +++ b/src/mongo-client.h @@ -50,6 +50,18 @@ typedef struct _mongo_connection mongo_connection; */ mongo_connection *mongo_connect (const char *host, int port); +/** Connect to a MongoDB server via a Unix socket. + * + * Connects to a single MongoDB server using a Unix Domain Socket. + * + * @param path is the path of the Unix socket. + * + * @returns A newly allocated mongo_connection object or NULL on + * error. It is the responsibility of the caller to free it once it is + * not used anymore. + */ +mongo_connection *mongo_unix_connect (const char *path); + /** Disconnect from a MongoDB server. * * @param conn is the connection object to disconnect from. diff --git a/src/mongo-sync.c b/src/mongo-sync.c index ab3ae16..ce26245 100644 --- a/src/mongo-sync.c +++ b/src/mongo-sync.c @@ -51,6 +51,29 @@ mongo_sync_connect (const gchar *host, gint port, return s; } +mongo_sync_connection * +mongo_sync_unix_connect (const gchar *path, gboolean slaveok) +{ + mongo_sync_connection *s; + mongo_connection *c; + + c = mongo_unix_connect (path); + if (!c) + return NULL; + s = g_realloc (c, sizeof (mongo_sync_connection)); + + s->slaveok = slaveok; + s->safe_mode = FALSE; + s->auto_reconnect = FALSE; + s->rs.seeds = NULL; + s->rs.hosts = NULL; + s->rs.primary = NULL; + s->last_error = NULL; + s->max_insert_size = MONGO_SYNC_DEFAULT_MAX_INSERT_SIZE; + + return s; +} + gboolean mongo_sync_conn_seed_add (mongo_sync_connection *conn, const gchar *host, gint port) diff --git a/src/mongo-sync.h b/src/mongo-sync.h index bc4f50e..515062a 100644 --- a/src/mongo-sync.h +++ b/src/mongo-sync.h @@ -67,6 +67,21 @@ mongo_sync_connection *mongo_sync_connect (const gchar *host, gint port, gboolean slaveok); +/** Synchronously connect to a MongoDB server via Unix socket. + * + * Sets up a synchronous connection to a MongoDB server. + * + * @param path is the path to the Unix Domain Socket to connect to. + * @param slaveok signals whether queries made against a slave are + * acceptable. + * + * @returns A newly allocated mongo_sync_connection object, or NULL on + * error. It is the responsibility of the caller to close and free the + * connection when appropriate. + */ +mongo_sync_connection *mongo_sync_unix_connect (const gchar *host, + gboolean slaveok); + /** Add a seed to an existing MongoDB connection. * * The seed list will be used for reconnects, prioritized before the -- 1.7.11.4
Hi, Algernon is the master for libmongo-client, so he'd have to ACK on that part. I was running through the patch, so I figured I'll share my comments for what it's worth. On Sun, 2012-08-12 at 03:57 +0200, Conrad Hoffmann wrote:
Add a separate connect function to both mongo-client and mongo-sync and demonstrate usage by adding this feature to the mongo-dump example program.
Replica sets have no support for Unix sockets so far.
Signed-off-by: Conrad Hoffmann <ch@bitfehler.net> --- examples/mongo-dump.c | 22 +++++++++++++++++----- src/mongo-client.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/mongo-client.h | 12 ++++++++++++ src/mongo-sync.c | 23 +++++++++++++++++++++++ src/mongo-sync.h | 15 +++++++++++++++ 5 files changed, 107 insertions(+), 5 deletions(-)
diff --git a/src/mongo-client.c b/src/mongo-client.c index ed931e4..67f9b64 100644 --- a/src/mongo-client.c +++ b/src/mongo-client.c @@ -109,6 +110,45 @@ mongo_connect (const char *host, int port) return conn; }
+mongo_connection * +mongo_unix_connect (const char *path) +{ + int len, fd = -1; + mongo_connection *conn; + struct sockaddr_un remote; + + if (!path) + { + errno = EINVAL; + return NULL; + } + + conn = g_new0 (mongo_connection, 1); + + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + errno = EADDRNOTAVAIL; + return NULL; + } + + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, path);
this could be a buffer overflow, if path is longer than the char array in the sockaddr_un struct.
+ len = strlen(remote.sun_path) + sizeof(remote.sun_family);
and this clearly has an assumption on the contents of the sockaddr_un struct. sizeof(remote) should also work, but if you really want to support very long path names for the unix domain socket (e.g. ones that exceed 108 chars, the limit in struct sockaddr_un), you'd have to allocate "remote" dynamically, and I'm not completely sure it'd actually work. And look what I've found while reading sys/un.h: /* Evaluate to actual length of the `sockaddr_un' structure. */ # define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ + strlen ((ptr)->sun_path)) I'm not sure that's portable though.
+ if (connect(fd, (struct sockaddr *)&remote, len) == -1) + { + close(fd); + g_free (conn); + + errno = EADDRNOTAVAIL; + return NULL; + } + + conn->fd = fd; + + return conn; +} + void mongo_disconnect (mongo_connection *conn) { diff --git a/src/mongo-client.h b/src/mongo-client.h index 28863e5..3917b05 100644 --- a/src/mongo-client.h +++ b/src/mongo-client.h @@ -50,6 +50,18 @@ typedef struct _mongo_connection mongo_connection; */ mongo_connection *mongo_connect (const char *host, int port);
+/** Connect to a MongoDB server via a Unix socket. + * + * Connects to a single MongoDB server using a Unix Domain Socket. + * + * @param path is the path of the Unix socket. + * + * @returns A newly allocated mongo_connection object or NULL on + * error. It is the responsibility of the caller to free it once it is + * not used anymore. + */ +mongo_connection *mongo_unix_connect (const char *path); + /** Disconnect from a MongoDB server. * * @param conn is the connection object to disconnect from. diff --git a/src/mongo-sync.c b/src/mongo-sync.c index ab3ae16..ce26245 100644 --- a/src/mongo-sync.c +++ b/src/mongo-sync.c @@ -51,6 +51,29 @@ mongo_sync_connect (const gchar *host, gint port, return s; }
+mongo_sync_connection * +mongo_sync_unix_connect (const gchar *path, gboolean slaveok) +{ + mongo_sync_connection *s; + mongo_connection *c; + + c = mongo_unix_connect (path); + if (!c) + return NULL; + s = g_realloc (c, sizeof (mongo_sync_connection)); + + s->slaveok = slaveok; + s->safe_mode = FALSE; + s->auto_reconnect = FALSE; + s->rs.seeds = NULL; + s->rs.hosts = NULL; + s->rs.primary = NULL; + s->last_error = NULL; + s->max_insert_size = MONGO_SYNC_DEFAULT_MAX_INSERT_SIZE; + + return s; +} + gboolean mongo_sync_conn_seed_add (mongo_sync_connection *conn, const gchar *host, gint port) diff --git a/src/mongo-sync.h b/src/mongo-sync.h index bc4f50e..515062a 100644 --- a/src/mongo-sync.h +++ b/src/mongo-sync.h @@ -67,6 +67,21 @@ mongo_sync_connection *mongo_sync_connect (const gchar *host, gint port, gboolean slaveok);
+/** Synchronously connect to a MongoDB server via Unix socket. + * + * Sets up a synchronous connection to a MongoDB server. + * + * @param path is the path to the Unix Domain Socket to connect to. + * @param slaveok signals whether queries made against a slave are + * acceptable. + * + * @returns A newly allocated mongo_sync_connection object, or NULL on + * error. It is the responsibility of the caller to close and free the + * connection when appropriate. + */ +mongo_sync_connection *mongo_sync_unix_connect (const gchar *host, + gboolean slaveok); + /** Add a seed to an existing MongoDB connection. * * The seed list will be used for reconnects, prioritized before the
-- Bazsi
Hi! Conrad Hoffmann <ch@bitfehler.net> writes:
It's more of a proof-of-concept thing, but in a quick session I put support for Unix sockets into libmongo-client. It may not be stunningly beautiful, but I actually used it (along with a second patch, which I will send shortly) to have syslog-ng write to mongodb via a Unix socket.
At a first glance, I like the patch, thanks for the great work! I'll try to review it properly as soon as possible - if there's anything, I'll get back to you.
I realize libmongo-client is also on GitHub, but the submodule pointed to a different repo, so I decided to just dump this here. :)
Mmm, yeah, we should fix the submodule at some point. But no matter, I see the patch either way ;) -- |8]
participants (3)
-
Balazs Scheidler
-
Conrad Hoffmann
-
Gergely Nagy