New API for zero-copy send and recv defined

Signed-off-by: Martin Sustrik <sustrik@250bpm.com>
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index e8ecab5..fae87ad 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -48,6 +48,8 @@
         sp_strerror.3
         sp_init.3
         sp_term.3
+        sp_allocmsg.3
+        sp_freemsg.3
         sp_socket.3
         sp_close.3
         sp_getsockopt.3
@@ -57,6 +59,8 @@
         sp_shutdown.3
         sp_send.3
         sp_recv.3
+        sp_sendmsg.3
+        sp_recvmsg.3
 
         )
 
diff --git a/doc/nanomsg.7.txt b/doc/nanomsg.7.txt
index d119a5f..47345c8 100644
--- a/doc/nanomsg.7.txt
+++ b/doc/nanomsg.7.txt
@@ -50,6 +50,18 @@
 Receive a message::
     linknanomsg:sp_recv[3]
 
+Allocate a message::
+    linknanomsg:sp_allocmsg[3]
+
+Deallocate a message::
+    linknanomsg:sp_freemsg[3]
+
+Send a message allocated by sp_allocmsg::
+    linknanomsg:sp_sendmsg[3]
+
+Receive a pre-allocated message::
+    linknanomsg:sp_recvmsg[3]
+
 Retrieve the current errno::
     linknanomsg:sp_errno[3]
 
diff --git a/doc/sp_allocmsg.3.txt b/doc/sp_allocmsg.3.txt
new file mode 100644
index 0000000..fe40c0b
--- /dev/null
+++ b/doc/sp_allocmsg.3.txt
@@ -0,0 +1,68 @@
+sp_allocmsg(3)
+==============
+
+NAME
+----
+sp_allocmsg - allocate a message
+
+
+SYNOPSIS
+--------
+*#include <sp/sp.h>*
+
+*void *sp_allocmsg (size_t 'size', int 'type');*
+
+
+DESCRIPTION
+-----------
+Allocate a message of the specified 'size' to be sent via
+linknanomsg:sp_sendmsg[3] function. The content of the message is undefined
+after allocation and is supposed to be filled in by the user. While
+linknanomsg:sp_send[3] allows to send arbitrary buffer, buffers allocated using
+_sp_allocmsg()_ may be more efficient for large messages as they allow for
+using zero-copy techniques.
+
+'type' parameter specifies type of allocation mechanism to use. Zero is the
+default one, however, individual transport mechanisms may define their
+own allocation mechanisms, such as allocating in shared memory or allocating
+a memory block pinned down to a physical memory address. Such allocation,
+when used with the transport that defines them, should be more efficient
+than the default allocation mechanism.
+
+
+RETURN VALUE
+------------
+If the function succeeds pointer to newly allocated buffer is returned.
+Otherwise, NULL is returned and 'errno' is set to to one of the values
+defined below.
+
+
+ERRORS
+------
+*EINVAL*::
+Supplied allocation 'type' is invalid.
+*ENOMEM*::
+Not enough memory to allocate the message.
+
+
+EXAMPLE
+-------
+
+----
+void *msg = sp_allocmsg (12, 0);
+memcpy (msg, "Hello world!", 12);
+sp_sendmsg (s, msg, 0);
+----
+
+
+SEE ALSO
+--------
+linknanomsg:sp_freemsg[3]
+linknanomsg:sp_sendmsg[3]
+linknanomsg:sp_recvmsg[3]
+linknanomsg:nanomsg[7]
+
+AUTHORS
+-------
+Martin Sustrik <sustrik@250bpm.com>
+
diff --git a/doc/sp_freemsg.3.txt b/doc/sp_freemsg.3.txt
new file mode 100644
index 0000000..6279802
--- /dev/null
+++ b/doc/sp_freemsg.3.txt
@@ -0,0 +1,54 @@
+sp_freemsg(3)
+=============
+
+NAME
+----
+sp_freemsg - deallocate a message
+
+
+SYNOPSIS
+--------
+*#include <sp/sp.h>*
+
+*int sp_freemsg (void '*msg');*
+
+
+DESCRIPTION
+-----------
+Deallocates a message allocated using linknanomsg:sp_allocmsg[3] function or
+received using linknanomsg:sp_recvmsg[3] function.
+
+
+RETURN VALUE
+------------
+If the function succeeds zero is returned. Otherwise, negative number is
+returned and 'errno' is set to to one of the values defined below.
+
+
+ERRORS
+------
+*EFAULT*::
+The message pointer is invalid.
+
+
+EXAMPLE
+-------
+
+----
+void *msg;
+sp_recvmsg (s, &msg, 0);
+sp_freemsg (msg);
+----
+
+
+SEE ALSO
+--------
+linknanomsg:sp_allocmsg[3]
+linknanomsg:sp_sendmsg[3]
+linknanomsg:sp_recvmsg[3]
+linknanomsg:nanomsg[7]
+
+AUTHORS
+-------
+Martin Sustrik <sustrik@250bpm.com>
+
diff --git a/doc/sp_recvmsg.3.txt b/doc/sp_recvmsg.3.txt
new file mode 100644
index 0000000..ef7c3b9
--- /dev/null
+++ b/doc/sp_recvmsg.3.txt
@@ -0,0 +1,82 @@
+sp_recvmsg(3)
+=============
+
+NAME
+----
+sp_recvmsg - receive a pre-allocated message
+
+
+SYNOPSIS
+--------
+*#include <sp/sp.h>*
+
+*int sp_recvmsg (int 's', void **msg, int 'flags');*
+
+
+DESCRIPTION
+-----------
+Receive a message from the socket 's' and store the pointer to the buffer into
+'msg' argument. If successful, the returned buffer has to be later deallocated
+using linknanomsg:sp_freemsg[3] function.
+
+The 'flags' argument is a combination of the flags defined below:
+
+*SP_DONTWAIT*::
+Specifies that the operation should be performed in non-blocking mode. If the
+message cannot be received straight away, the function will fail with 'errno'
+set to EAGAIN.
+
+
+RETURN VALUE
+------------
+If the function succeeds number of bytes in the message is returned. Otherwise,
+negative number is returned and 'errno' is set to to one of the values defined
+below.
+
+
+ERRORS
+------
+*EFAULT*::
+The library is not initialised.
+*EBADF*::
+The provided socket is invalid.
+*ENOTSUP*::
+The operation is not supported by this socket type.
+*EFSM*::
+The operation cannot be performed on this socket at the moment because socket is
+not in the appropriate state.  This error may occur with socket types that
+switch between several states.
+*EAGAIN*::
+Non-blocking mode was requested and there's no message to receive at the moment.
+*EINTR*::
+The operation was interrupted by delivery of a signal before the message was
+received.
+*ETIMEDOUT*::
+Individual socket types may define their own specific timeouts. If such timeout
+is hit this error will be returned.
+*ETERM*::
+The library is terminating.
+
+EXAMPLE
+-------
+
+----
+void *msg;
+sp_recvmsg (s, &msg, 0);
+sp_freemsg (msg);
+----
+
+
+SEE ALSO
+--------
+linknanomsg:sp_recv[3]
+linknanomsg:sp_allocmsg[3]
+linknanomsg:sp_freemsg[3]
+linknanomsg:sp_sendmsg[3]
+linknanomsg:nanomsg[7]
+
+
+AUTHORS
+-------
+Martin Sustrik <sustrik@250bpm.com>
+
diff --git a/doc/sp_sendmsg.3.txt b/doc/sp_sendmsg.3.txt
new file mode 100644
index 0000000..77b9275
--- /dev/null
+++ b/doc/sp_sendmsg.3.txt
@@ -0,0 +1,89 @@
+sp_sendmsg(3)
+=============
+
+NAME
+----
+sp_sendmsg - send a message allocated by sp_allocmsg
+
+
+SYNOPSIS
+--------
+*#include <sp/sp.h>*
+
+*int sp_sendmsg (int 's', void '*msg', int 'flags');*
+
+DESCRIPTION
+-----------
+The function will send a message containing the data from message 'msg' to
+the socket 's'. The message must be allocated using linknanomsg:sp_allocmsg[3]
+function.
+
+To which of the peers will the message be sent to is determined by
+the particular socket type.
+
+When the function succeeds, message pointer 'msg' becomes invalid and should
+not be used any more or deallocated by the user. It will be deallocated
+automatically by the library.
+
+The 'flags' argument is a combination of the flags defined below:
+
+*SP_DONTWAIT*::
+Specifies that the operation should be performed in non-blocking mode. If the
+message cannot be sent straight away, the function will fail with 'errno' set
+to EAGAIN.
+
+
+RETURN VALUE
+------------
+If the function succeeds number of bytes in the message is returned. Otherwise,
+negative number is returned and 'errno' is set to to one of the values defined
+below.
+
+
+ERRORS
+------
+*EFAULT*::
+Either the library is not initialised or 'msg' is not a valid message.
+*EBADF*::
+The provided socket is invalid.
+*ENOTSUP*::
+The operation is not supported by this socket type.
+*EFSM*::
+The operation cannot be performed on this socket at the moment because socket is
+not in the appropriate state.  This error may occur with socket types that
+switch between several states.
+*EAGAIN*::
+Non-blocking mode was requested and the message cannot be sent at the moment.
+*EINTR*::
+The operation was interrupted by delivery of a signal before the message was
+sent.
+*ETIMEDOUT*::
+Individual socket types may define their own specific timeouts. If such timeout
+is hit this error will be returned.
+*ETERM*::
+The library is terminating.
+
+
+EXAMPLE
+-------
+
+----
+void *msg = sp_allocmsg (12, 0);
+memcpy (msg, "Hello world!", 12);
+sp_sendmsg (s, msg, 0);
+----
+
+
+SEE ALSO
+--------
+linknanomsg:sp_send[3]
+linknanomsg:sp_allocmsg[3]
+linknanomsg:sp_freemsg[3]
+linknanomsg:sp_recvmsg[3]
+linknanomsg:nanomsg[7]
+
+
+AUTHORS
+-------
+Martin Sustrik <sustrik@250bpm.com>
+
diff --git a/src/core/ctx.c b/src/core/ctx.c
index 259963f..2b5d5f6 100644
--- a/src/core/ctx.c
+++ b/src/core/ctx.c
@@ -279,6 +279,16 @@
     return 0;
 }
 
+void *sp_allocmsg (size_t size, int type)
+{
+    sp_assert (0);
+}
+
+int sp_freemsg (void *msg)
+{
+    sp_assert (0);
+}
+
 int sp_socket (int domain, int protocol)
 {
     int s;
@@ -482,6 +492,16 @@
     return (int) len;
 }
 
+int sp_sendmsg (int s, void *msg, int flags)
+{
+    sp_assert (0);
+}
+
+int sp_recvmsg (int s, void **msg, int flags)
+{
+    sp_assert (0);
+}
+
 static void sp_ctx_add_transport (struct sp_transport *transport)
 {
     transport->init ();
diff --git a/src/sp.h b/src/sp.h
index 66bc79e..e3895d6 100644
--- a/src/sp.h
+++ b/src/sp.h
@@ -135,6 +135,13 @@
 SP_EXPORT int sp_term (void);
 
 /******************************************************************************/
+/*  Message allocation.                                                       */
+/******************************************************************************/
+
+SP_EXPORT void *sp_allocmsg (size_t size, int type);
+SP_EXPORT int sp_freemsg (void *msg);
+
+/******************************************************************************/
 /*  SP socket definition.                                                     */
 /******************************************************************************/
 
@@ -172,6 +179,8 @@
 SP_EXPORT int sp_shutdown (int s, int how);
 SP_EXPORT int sp_send (int s, const void *buf, size_t len, int flags);
 SP_EXPORT int sp_recv (int s, void *buf, size_t len, int flags);
+SP_EXPORT int sp_sendmsg (int s, void *msg, int flags);
+SP_EXPORT int sp_recvmsg (int s, void **msg, int flags);
 
 #undef SP_EXPORT
 
diff --git a/src/utils/msg.h b/src/utils/msg.h
index cf02ecd..2178aa0 100644
--- a/src/utils/msg.h
+++ b/src/utils/msg.h
@@ -34,8 +34,8 @@
 struct sp_content
 {
     size_t size;
-    /* Actual message data follow the 'size' field. */
 
+    /* Actual message data follow the sp_content structure. */
 };
 
 /*  This class represents an SP message. */