aboutsummaryrefslogtreecommitdiff
path: root/docs/ref/api/msg.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/ref/api/msg.md')
-rw-r--r--docs/ref/api/msg.md274
1 files changed, 274 insertions, 0 deletions
diff --git a/docs/ref/api/msg.md b/docs/ref/api/msg.md
new file mode 100644
index 00000000..569d4692
--- /dev/null
+++ b/docs/ref/api/msg.md
@@ -0,0 +1,274 @@
+# Messages
+
+Messages {{hi:messages}} in Scalability Protocols are the fundamental unit of
+transmission and reception, as these protocols are fundamentally message-oriented.
+
+Messages have a [body][nng_msg_body]{{hi:message body}}, containing the application-supplied
+payload, and a [header][nng_msg_header]{{hi:message header}}, containing protocol specific routing and similar
+related information.
+
+> [!TIP]
+> Only applications using [raw mode][raw] need to access the message header.
+> Very few _NNG_ applications do this.
+
+## Message Structure
+
+```c
+typedef struct nng_msg nng_msg;
+```
+
+The {{i:`nng_msg`}} structure represents a single message. It carries a body
+and a header.
+
+### Create a Message
+
+```c
+int nng_msg_alloc(nng_msg **msgp, size_t size);
+```
+
+The {{i:`nng_msg_alloc`}} function allocates a new message.
+It takes a _size_ argument, and returns a message
+with a preallocated body of that size in the _msgp_ parameter.
+
+If it succeeds, it returns zero, otherwise this function may return `NNG_ENOMEM`,
+indicating that insufficient memory is available to allocate a new message.
+
+### Destroy a Message
+
+```c
+void nng_msg_free(nng_msg *msg);
+```
+
+The {{i:`nng_msg_free`}} function deallocates a message.
+
+### Duplicate a Message
+
+```c
+int nng_msg_dup(nng_msg **dup, nng_msg *msg);
+```
+
+The {{i:`nng_msg_dup`}} function duplicates the message _msg_, storing a pointer
+to the new duplicate in _dup_. This function also returns zero on succes, or `NNG_ENOMEM`
+if memory is exhausted.
+
+## Message Size and Capacity
+
+```c
+size_t nng_msg_capacity(nng_msg *msg);
+int nng_msg_realloc(nng_msg *msg, size_t size);
+int nng_msg_reserve(nng_msg *msg, size_t capacity);
+```
+
+Messages have a certain amount of pre-reserved space, which may exceed the total
+size of the message. This allows for content to be added to the message later,
+without necessarily performing a reallocation.
+
+The {{i:`nng_msg_capacity`}} function returns the amount of prereserved space.
+If a message size change is required, and the new size will fit within the capacity
+reported by this function, then change will be done without a reallocation, and
+likely without a data copy as well.
+
+> [!TIP]
+> The capacity reported by `nng_msg_capacity` may not include reserved headroom, which
+> is present to allow a very limited amount of content to be inserted in front of the
+> message without requiring the rest of the message to be copied.
+
+The message size may be changed by use of the {{i:`nng_msg_realloc`}} function. This
+function will reallocate the underlying memory for the message _msg_,
+preserving contents while doing so.
+If the new size is smaller than the original message, it will
+truncate the message, but not perform any allocations.
+If reallocation fails due to insufficient memory, then the original is left intact.
+This function returns either zero, or `NNG_ENOMEM`.
+
+The {{i:`nng_msg_reserve`}} function ensures that the total message capacity
+is at least _capacity_ bytes. Use of this function to ensure the total anticipated
+capacity is present in the message may help prevent many small allocations.
+
+Both `nng_msg_realloc` and `nng_msg_reserve` return zero on success, or may return
+`NNG_ENOMEM` if insufficient memory exists to preform allocation.
+
+> [!IMPORTANT]
+> Any pointers to message content obtained before a call to `nng_msg_realloc` or
+> `nng_msg_reserve` (or any other function that changes the message size) should be
+> treated as invalid, as the locations pointed to may be deallocated by these functions.
+
+## Message Body
+
+```c
+void *nng_msg_body(nng_msg *msg);
+size_t nng_msg_len(nng_msg *msg);
+```
+
+The body and body length of _msg_ are returned by {{i:`nng_msg_body}}` and
+{{i:`nng_msg_len`}}, respectively.
+
+### Clear the Body
+
+```c
+void *nng_msg_clear(nng_msg *msg);
+```
+
+The {{i:`nng_msg_clear`}} simply resets the total message body length to zero, but does
+not affect the capacity. It does not change the underlying bytes of the message.
+
+### Add to Body
+
+```c
+int nng_msg_append(nng_msg *msg, const void *val, size_t size);
+int nng_msg_append_u16(nng_msg *msg, uint16_t val16);
+int nng_msg_append_u32(nng_msg *msg, uint32_t val32);
+int nng_msg_append_u64(nng_msg *msg, uint64_t val64);
+
+int nng_msg_insert(nng_msg *msg, const void *val, size_t size);
+int nng_msg_insert_u16(nng_msg *msg, uint16_t val16);
+int nng_msg_insert_u32(nng_msg *msg, uint32_t val32);
+int nng_msg_insert_u64(nng_msg *msg, uint64_t val64);
+```
+
+Appending data to a message body is done by using the {{i:`nng_msg_append`}} functions.
+The base `nng_msg_append` function appends _size_ bytes of untyped data to the end of the
+message.
+
+Use of the typed versions, ending in suffixes `_u16`, `_u32`, and `_u64` allows
+for unsigned integers to be appended directly. The integers are encoded in network byte order, with
+the most significant byte appearing first. The message body will by two, four, or eight
+bytes accordingly.
+
+Data may inserted before the rest of the message body by using the {{i:`nng_msg_insert`}} functions.
+This will attempt to use "headroom" in the message to avoid a data copy.
+Otherwise they are like the `nng_msg_append` functions except that the put the data in front
+of the messages instead of at the end.
+
+> [!TIP]
+> Message headroom is limited, so `nng_msg_insert` is best used sparingly.
+> It is much more efficient to build the message content from start to end
+> using `nng_msg_append`.
+
+### Consume From Body
+
+```c
+int nng_msg_chop(nng_msg *msg, size_t size);
+int nng_msg_chop_u16(nng_msg *msg, uint16_t *val16);
+int nng_msg_chop_u32(nng_msg *msg, uint32_t *val32);
+int nng_msg_chop_u64(nng_msg *msg, uint64_t *val64);
+
+int nng_msg_trim(nng_msg *msg, size_t size);
+int nng_msg_trim_u16(nng_msg *msg, uint16_t *val16);
+int nng_msg_trim_u32(nng_msg *msg, uint32_t *val32);
+int nng_msg_trim_u64(nng_msg *msg, uint64_t *val64);
+```
+
+The {{i:`nng_msg_chop`}} functions remove data from the end of the body of message _msg_,
+reducing the message length by either _size_, or the appropriate value size.
+
+The {{i:`nng_msg_trim`}} functions remove data from the beginning of the message body of _msg_.
+but are otherwise just like the `nng_msg_chop` functions.
+
+If the message is not big enough to remove requisite amount of bytes, these functions
+return `NNG_EINVAL`. Otherwise they return zero.
+
+Additionally, functions with typed suffixes (`_u16`, `_u32`, `_u64`) decode the data and return it
+through the appropriate _val_ pointer.
+
+The data is assumed to have been in network byte order in the message, but is returned in
+the native machine byte order. The appropriate number of bytes is consumed for each of these types,
+so two bytes for `_u16`, four bytes for `_u32`, and eight bytes for `_u64`.
+
+## Message Header
+
+```c
+void *nng_msg_header(nng_msg *msg);
+size_t nng_msg_header_len(nng_msg *msg);
+```
+
+The header and header length of _msg_ are returned by {{i:`nng_msg_header}}` and
+{{i:`nng_msg_header_len`}}, respectively.
+
+The message headers are generally intended for limited use, to store protocol headers.
+
+> [!IMPORTANT]
+> The message headers are for protocol and transport headers, and not for general
+> application payloads. Misuse of the header may prevent the application from functioning
+> properly.
+
+### Clear the Header
+
+```c
+void *nng_msg_header_clear(nng_msg *msg);
+```
+
+The {{i:`nng_msg_header_clear`}} simply resets the total message header length to zero.
+
+### Append or Insert Header
+
+Appending data to a message header is done by using the {{i:`nng_msg_header_append`}} functions,
+and inserting data in the header is done using the {{i:`nng_msg_header_insert`}} functions.
+
+These functions act just like the [`nng_msg_append`][nng_msg_append] and [`nng_msg_insert`][nng_msg_insert]
+functions, except that they operate on the message header rather than the message body.
+
+### Consume from Header
+
+The {{i:`nng_msg_header_trim`}} functions remove data from the beginning of the message header,
+and the {{i:`nng_msg_header_chop`}} functions remove data from the end of the message header.
+
+These functions act just like the [`nng_msg_trim`][nng_msg_trim] and [`nng_msg_chop`][nng_msg_chop]
+functions, except that they operate the message header rather than the message body.
+
+## Message Pipe
+
+```c
+nng_pipe nng_msg_get_pipe(nng_msg *msg);
+void nng_msg_get_pipe(nng_msg *msg, nng_pipe p);
+```
+
+The {{i:`nng_msg_set_pipe`}} function sets the [pipe][pipe] associated with _msg_ to _p_.
+This is most often useful when used with protocols that support directing
+a message to a specific peer.
+For example the [_PAIR_][pair] version 1 protocol can do
+this when `NNG_OPT_PAIR1_POLY` mode is set.
+
+The {{i:`nng_msg_get_pipe`}} function returns the pipe that was previously set on the message _m_,
+either directly by the application, or when the message was received by the protocol.
+
+> [!NOTE]
+> Not all protocols support overriding the destination pipe.
+
+## Examples
+
+### Example 1: Preparing a message for use
+
+```c
+ #include <nng/nng.h>
+
+ nng_msg *m;
+ if (nng_msg_alloc(&m, strlen("content") + 1) != 0) {
+ // handle error
+ }
+ strcpy(nng_msg_body(m), "content");
+```
+
+### Example 2: Preallocating message content
+
+```c
+ if (nng_msg_alloc(&m, 1024) != 0) {
+ // handle error
+ }
+ while ((val64 = next_datum()) != 0) P
+ if (nng_msg_append_u64(m, val64) != 0) {
+ // handle error
+ }
+ }
+```
+
+[nng_msg_body]: #message-body
+[nng_msg_header]: #message-header
+[nng_msg_append]: #add-to-body
+[nng_msg_insert]: #add-to-body
+[nng_msg_trim]: #consume-from-body
+[nng_msg_chop]: #consume-from-body
+[nng_msg_header_append]: #append-or-insert-header
+[raw]: TODO.md
+[pair]: ../proto/pair.md
+[pipe]: TODO.md