summaryrefslogtreecommitdiff
path: root/src/mongo-wire.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo-wire.h')
-rw-r--r--src/mongo-wire.h433
1 files changed, 433 insertions, 0 deletions
diff --git a/src/mongo-wire.h b/src/mongo-wire.h
new file mode 100644
index 0000000..081a3e2
--- /dev/null
+++ b/src/mongo-wire.h
@@ -0,0 +1,433 @@
+/* mongo-wire.h - libmongo-client's MongoDB wire protocoll implementation.
+ * Copyright 2011, 2012 Gergely Nagy <algernon@balabit.hu>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** @file src/mongo-wire.h
+ * MongoDB Wire Protocol API public header.
+ */
+
+#ifndef LIBMONGO_CLIENT_MONGO_WIRE_H
+#define LIBMONGO_CLIENT_MONGO_WIRE_H 1
+
+#include <glib.h>
+
+#include <bson.h>
+
+G_BEGIN_DECLS
+
+/** @defgroup mongo_wire Mongo Wire Protocol
+ *
+ * The structures and functions within this module implement the
+ * MongoDB wire protocol: functions to assemble various commands into
+ * binary blobs that can be sent over the wire.
+ *
+ * @see mongo_client
+ *
+ * @addtogroup mongo_wire
+ * @{
+ */
+
+/** @defgroup mongo_wire_packet Packets
+ *
+ * @addtogroup mongo_wire_packet
+ * @{
+ */
+
+/** Mongo packet header.
+ *
+ * Every mongo packet has a header like this. Normally, one does not
+ * need to touch it, though.
+ */
+typedef struct
+{
+ gint32 length; /**< Full length of the packet, including the
+ header. */
+ gint32 id; /**< Sequence ID, used when MongoDB responds to a
+ command. */
+ gint32 resp_to; /**< ID the response is an answer to. Only sent by
+ the MongoDB server, never set on client-side. */
+ gint32 opcode; /**< The opcode of the command. @see
+ mongo_wire_opcode. <*/
+} mongo_packet_header;
+
+/** An opaque Mongo Packet on the wire.
+ *
+ * This structure contains the binary data that can be written
+ * straight to the wire.
+ */
+typedef struct _mongo_packet mongo_packet;
+
+/** Create an empty packet.
+ *
+ * Creates an empty packet to be filled in later with
+ * mongo_wire_packet_set_header() and mongo_packet_set_data().
+ *
+ * @returns A newly allocated packet, or NULL on error.
+ */
+mongo_packet *mongo_wire_packet_new (void);
+
+/** Get the header data of a packet.
+ *
+ * Retrieve the mongo packet's header data.
+ *
+ * @param p is the packet which header we seek.
+ * @param header is a pointer to a variable which will hold the data.
+ *
+ * @note Allocating the @a header is the responsibility of the caller.
+ *
+ * @returns TRUE on success, FALSE otherwise.
+ */
+gboolean mongo_wire_packet_get_header (const mongo_packet *p,
+ mongo_packet_header *header);
+
+/** Set the header data of a packet.
+ *
+ * Override the mongo packet's header data.
+ *
+ * @note No sanity checks are done, use this function with great care.
+ *
+ * @param p is the packet whose header we want to override.
+ * @param header is the header structure to use.
+ *
+ * @returns TRUE on success, FALSE otherwise.
+ */
+gboolean mongo_wire_packet_set_header (mongo_packet *p,
+ const mongo_packet_header *header);
+
+/** Get the data part of a packet.
+ *
+ * Retrieve the raw binary blob of the mongo packet's data.
+ *
+ * @param p is the packet which header we seek.
+ * @param data is a pointer to a variable which will hold the data.
+ *
+ * @note The @a data parameter will point to an internal structure,
+ * which shall not be freed or written to.
+ *
+ * @returns The size of the data, or -1 on error.
+ */
+gint32 mongo_wire_packet_get_data (const mongo_packet *p, const guint8 **data);
+
+/** Set the data part of a packet.
+ *
+ * Overrides the data part of a packet, adjusting the packet length in
+ * the header too.
+ *
+ * @note No sanity checks are performed on the data, it is the
+ * caller's responsibility to supply valid information.
+ *
+ * @param p is the packet whose data is to be set.
+ * @param data is the data to set.
+ * @param size is the size of the data.
+ *
+ * @returns TRUE on success, FALSE otherwise.
+ */
+gboolean mongo_wire_packet_set_data (mongo_packet *p, const guint8 *data,
+ gint32 size);
+
+/** Free up a mongo packet.
+ *
+ * @param p is the packet to free.
+ *
+ * @note The packet shall not be used afterwards.
+ */
+void mongo_wire_packet_free (mongo_packet *p);
+
+/** @} */
+
+/** @defgroup mongo_wire_reply Reply handling
+ *
+ * @addtogroup mongo_wire_reply
+ * @{
+ */
+
+/** Flags the server can set in replies. */
+enum
+ {
+ /** Set when get_more is called but the cursor id is invalid. */
+ MONGO_REPLY_FLAG_NO_CURSOR = 0x1,
+ /** Set when the query failed. */
+ MONGO_REPLY_FLAG_QUERY_FAIL = 0x2,
+ /** Set when the server suppots the AwaitData query option.
+ * If not set, the client should sleep a little between get_more
+ * calls on a tailable cursor. On Mongo >= 1.6, this flag is
+ * always set.
+ */
+ MONGO_REPLY_FLAG_AWAITCAPABLE = 0x8
+ };
+
+/** Mongo reply packet header.
+ */
+#pragma pack(1)
+typedef struct
+{
+ gint32 flags; /**< Response flags. */
+ gint64 cursor_id; /**< Cursor ID, in case the client needs to do
+ get_more requests. */
+ gint32 start; /**< Starting position of the reply within the
+ cursor. */
+ gint32 returned; /**< Number of documents returned in the reply. */
+} mongo_reply_packet_header;
+#pragma pack()
+
+/** Get the header of a reply packet.
+ *
+ * @param p is the packet to retrieve the reply header from.
+ * @param hdr is a pointer to a variable where the reply header will
+ * be stored.
+ *
+ * @note It is the responsibility of the caller to allocate space for
+ * the header.
+ *
+ * @returns TRUE on success, FALSE otherwise.
+ */
+gboolean mongo_wire_reply_packet_get_header (const mongo_packet *p,
+ mongo_reply_packet_header *hdr);
+
+/** Get the full data part of a reply packet.
+ *
+ * The result will include the full, unparsed data part of the reply.
+ *
+ * @param p is the packet to retrieve the data from.
+ * @param data is a pointer to a variable where the replys data can be
+ * stored.
+ *
+ * @note The @a data variable will point to an internal structure,
+ * which must not be freed or modified.
+ *
+ * @returns TRUE on success, FALSE otherwise.
+ */
+gboolean mongo_wire_reply_packet_get_data (const mongo_packet *p,
+ const guint8 **data);
+
+/** Get the Nth document from a reply packet.
+ *
+ * @param p is the packet to retrieve a document from.
+ * @param n is the number of the document to retrieve.
+ * @param doc is a pointer to a variable to hold the BSON document.
+ *
+ * @note The @a doc variable will be a newly allocated object, it is
+ * the responsibility of the caller to free it once it is not needed
+ * anymore.
+ *
+ * @returns TRUE on success, FALSE otherwise.
+ */
+gboolean mongo_wire_reply_packet_get_nth_document (const mongo_packet *p,
+ gint32 n,
+ bson **doc);
+
+/** @}*/
+
+/** @defgroup mongo_wire_cmd Commands
+ *
+ * Each command has an @a id parameter, which can be used to track
+ * replies to various commands. It is the responsibility of the caller
+ * to keep track of IDs.
+ *
+ * @addtogroup mongo_wire_cmd
+ * @{
+ */
+
+/** Flags available for the update command.
+ * @see mongo_wire_cmd_update().
+ */
+enum
+ {
+ /** When set, inserts if no matching document was found. */
+ MONGO_WIRE_FLAG_UPDATE_UPSERT = 0x1,
+ /** When set, all matching documents will be updated, not just
+ the first. */
+ MONGO_WIRE_FLAG_UPDATE_MULTI = 0x2
+ };
+
+/** Construct an update command.
+ *
+ * @param id is the sequence id.
+ * @param ns is the namespace, the database and collection name
+ * concatenated, and separated with a single dot.
+ * @param flags are the flags for the update command. Available flags
+ * are #MONGO_WIRE_FLAG_UPDATE_UPSERT and
+ * #MONGO_WIRE_FLAG_UPDATE_MULTI.
+ * @param selector is the BSON document that will act as the selector.
+ * @param update is the BSON document that contains the updated values.
+ *
+ * @returns A newly allocated packet, or NULL on error. It is the
+ * responsibility of the caller to free the packet once it is not used
+ * anymore.
+ */
+mongo_packet *mongo_wire_cmd_update (gint32 id, const gchar *ns,
+ gint32 flags, const bson *selector,
+ const bson *update);
+
+/** Construct an insert command.
+ *
+ * @param id is the sequence id.
+ * @param ns is the namespace, the database and collection name
+ * concatenated, and separated with a single dot.
+ * @tparam docs are the BSON documents to insert. One must close the
+ * list with a NULL value.
+ *
+ * @returns A newly allocated packet, or NULL on error. It is the
+ * responsibility of the caller to free the packet once it is not used
+ * anymore.
+ */
+mongo_packet *mongo_wire_cmd_insert (gint32 id, const gchar *ns, ...)
+ G_GNUC_NULL_TERMINATED;
+
+/** Construct an insert command with N documents.
+ *
+ * @param id is the sequence id.
+ * @param ns is the namespace, the database and collection name
+ * concatenated, and separated with a single dot.
+ * @param n is the number of documents to insert.
+ * @param docs is the array containing the bson documents to insert.
+ *
+ * @returns A newly allocated packet, or NULL on error. It is the
+ * responsibility of the caller to free the packet once it is not used
+ * anymore.
+ */
+mongo_packet *mongo_wire_cmd_insert_n (gint32 id, const gchar *ns, gint32 n,
+ const bson **docs);
+
+/** Flags available for the query command.
+ * @see mongo_wire_cmd_query().
+ */
+enum
+ {
+ /** Set the TailableCursor flag on the query. */
+ MONGO_WIRE_FLAG_QUERY_TAILABLE_CURSOR = 1 << 1,
+ /** Allow queries made against a replica slave. */
+ MONGO_WIRE_FLAG_QUERY_SLAVE_OK = 1 << 2,
+ /** Disable cursor timeout. */
+ MONGO_WIRE_FLAG_QUERY_NO_CURSOR_TIMEOUT = 1 << 4,
+ /** Block if at the end of the data block, awaiting data.
+ * Use only with #MONGO_WIRE_FLAG_QUERY_TAILABLE_CURSOR!
+ */
+ MONGO_WIRE_FLAG_QUERY_AWAIT_DATA = 1 << 5,
+ /** Stream the data down full blast in multiple packages.
+ * When set, the client is not allowed not to read all the data,
+ * unless it closes connection.
+ */
+ MONGO_WIRE_FLAG_QUERY_EXHAUST = 1 << 6,
+ /** Allow partial results in a sharded environment.
+ * In case one or more required shards are down, with this flag
+ * set, partial results will be returned instead of failing.
+ */
+ MONGO_WIRE_FLAG_QUERY_PARTIAL_RESULTS = 1 << 7
+ };
+
+/** Construct a query command.
+ *
+ * @param id is the sequence id.
+ * @param ns is the namespace, the database and collection name
+ * concatenated, and separated with a single dot.
+ * @param flags are the query options. Available flags are:
+ * #MONGO_WIRE_FLAG_QUERY_TAILABLE_CURSOR,
+ * #MONGO_WIRE_FLAG_QUERY_SLAVE_OK,
+ * #MONGO_WIRE_FLAG_QUERY_NO_CURSOR_TIMEOUT,
+ * #MONGO_WIRE_FLAG_QUERY_AWAIT_DATA, #MONGO_WIRE_FLAG_QUERY_EXHAUST.
+ * @param skip is the number of documents to skip.
+ * @param ret is the number of documents to return.
+ * @param query is the query BSON object.
+ * @param sel is the (optional) selector BSON object indicating the
+ * fields to return. Passing NULL will return all fields.
+ *
+ * @returns A newly allocated packet, or NULL on error. It is the
+ * responsibility of the caller to free the packet once it is not used
+ * anymore.
+ */
+mongo_packet *mongo_wire_cmd_query (gint32 id, const gchar *ns, gint32 flags,
+ gint32 skip, gint32 ret, const bson *query,
+ const bson *sel);
+
+/** Construct a get more command.
+ *
+ * @param id is the sequence id.
+ * @param ns is the namespace, the database and collection name
+ * concatenated, and separated with a single dot.
+ * @param ret is the number of documents to return.
+ * @param cursor_id is the ID of the cursor to use.
+ *
+ * @returns A newly allocated packet, or NULL on error. It is the
+ * responsibility of the caller to free the packet once it is not used
+ * anymore.
+ */
+mongo_packet *mongo_wire_cmd_get_more (gint32 id, const gchar *ns,
+ gint32 ret, gint64 cursor_id);
+
+/** Flags available for the delete command.
+ */
+enum
+ {
+ /** Only remove the first match. */
+ MONGO_WIRE_FLAG_DELETE_SINGLE = 0x1
+ };
+
+/** Construct a delete command.
+ *
+ * @param id is the sequence id.
+ * @param ns is the namespace, the database and collection name
+ * concatenated, and separated with a single dot.
+ * @param flags are the delete options. The only available flag is
+ * MONGO_WIRE_FLAG_DELETE_SINGLE.
+ * @param sel is the BSON object to use as a selector.
+ *
+ * @returns A newly allocated packet, or NULL on error. It is the
+ * responsibility of the caller to free the packet once it is not used
+ * anymore.
+ */
+mongo_packet *mongo_wire_cmd_delete (gint32 id, const gchar *ns,
+ gint32 flags, const bson *sel);
+
+/** Construct a kill cursors command.
+ *
+ * @param id is the sequence id.
+ * @param n is the number of cursors to delete.
+ * @tparam cursor_ids are the ids of the cursors to delete.
+ *
+ * @note One must supply exaclty @a n number of cursor IDs.
+ *
+ * @returns A newly allocated packet, or NULL on error. It is the
+ * responsibility of the caller to free the packet once it is not used
+ * anymore.
+ */
+mongo_packet *mongo_wire_cmd_kill_cursors (gint32 id, gint32 n, ...);
+
+/** Construct a custom command.
+ *
+ * Custom commands are queries run in the db.$cmd namespace. The
+ * commands themselves are queries, and as such, BSON objects.
+ *
+ * @param id is the sequence id.
+ * @param db is the database in which the command shall be run.
+ * @param flags are the query flags. See mongo_wire_cmd_query() for a
+ * list.
+ * @param command is the BSON object representing the command.
+ *
+ * @returns A newly allocated packet, or NULL on error. It is the
+ * responsibility of the caller to free the packet once it is not used
+ * anymore.
+ */
+mongo_packet *mongo_wire_cmd_custom (gint32 id, const gchar *db,
+ gint32 flags,
+ const bson *command);
+
+/** @} */
+
+/** @} */
+
+G_END_DECLS
+
+#endif