.. This work is licensed under a Creative Commons Attribution 4.0 International License. | |
.. SPDX-License-Identifier: CC-BY-4.0 | |
.. CAUTION: this document is generated from source in doc/src/rtd. | |
.. To make changes edit the source and recompile the document. | |
.. Do NOT make changes directly to .rst or .md files. | |
============================================================================================ | |
Man Page: rmr_send_msg | |
============================================================================================ | |
RMR Library Functions | |
============================================================================================ | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_send_msg | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_send_msg( void* vctx, rmr_mbuf_t* msg ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_send_msg function accepts a message buffer from the | |
user application and attempts to send it. The destination of | |
the message is selected based on the message type specified | |
in the message buffer, and the matching information in the | |
routing tables which are currently in use by the RMR library. | |
This may actually result in the sending of the message to | |
multiple destinations which could degrade expected overall | |
performance of the user application. (Limiting excessive | |
sending of messages is the responsibility of the | |
application(s) responsible for building the routing table | |
used by the RMR library, and not the responsibility of the | |
library.) | |
Retries | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The send operations in RMR will retry *soft* send failures | |
until one of three conditions occurs: | |
1. | |
The message is sent without error | |
2. | |
The underlying transport reports a *hard* failure | |
3. | |
The maximum number of retry loops has been attempted | |
A retry loop consists of approximately 1000 send attempts | |
**without** any intervening calls to *sleep()* or *usleep().* | |
The number of retry loops defaults to 1, thus a maximum of | |
1000 send attempts is performed before returning to the user | |
application. This value can be set at any point after RMr | |
initialisation using the *rmr_set_stimeout()* function | |
allowing the user application to completely disable retires | |
(set to 0), or to increase the number of retry loops. | |
Transport Level Blocking | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The underlying transport mechanism used to send messages is | |
configured in *non-blocking* mode. This means that if a | |
message cannot be sent immediately the transport mechanism | |
will **not** pause with the assumption that the inability to | |
send will clear quickly (within a few milliseconds). This | |
means that when the retry loop is completely disabled (set to | |
0), that the failure to accept a message for sending by the | |
underlying mechanisms (software or hardware) will be reported | |
immediately to the user application. | |
It should be noted that depending on the underlying transport | |
mechanism being used, it is extremely likely that retry | |
conditions will happen during normal operations. These are | |
completely out of RMR's control, and there is nothing that | |
RMR can do to avoid or mitigate these other than by allowing | |
RMR to retry the send operation, and even then it is possible | |
(e.g., during connection reattempts), that a single retry | |
loop is not enough to guarantee a successful send. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a new message buffer, with an empty payload, is | |
returned for the application to use for the next send. The | |
state in this buffer will reflect the overall send operation | |
state and will be RMR_OK when the send was successful. | |
When the message cannot be successfully sent this function | |
will return the unsent (original) message buffer with the | |
state set to indicate the reason for failure. The value of | |
*errno* may also be set to reflect a more detailed failure | |
reason if it is known. | |
In the event of extreme failure, a nil pointer is returned. | |
In this case the value of errno might be of some use, for | |
documentation, but there will be little that the user | |
application can do other than to move on. | |
**CAUTION:** In some cases it is extremely likely that the | |
message returned by the send function does **not** reference | |
the same memory structure. Thus is important for the user | |
programme to capture the new pointer for future use or to be | |
passed to rmr_free(). If you are experiencing either double | |
free errors or segment faults in either rmr_free() or | |
rmr_send_msg(), ensure that the return value from this | |
function is being captured and used. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The following values may be passed back in the *state* field | |
of the returned message buffer. | |
RMR_RETRY | |
The message could not be sent, but the underlying | |
transport mechanism indicates that the failure is | |
temporary. If the send operation is tried again it might | |
be successful. | |
RMR_SEND_FAILED | |
The send operation was not successful and the underlying | |
transport mechanism indicates a permanent (hard) failure; | |
retrying the send is not possible. | |
RMR_ERR_BADARG | |
The message buffer pointer did not refer to a valid | |
message. | |
RMR_ERR_NOHDR | |
The header in the message buffer was not valid or | |
corrupted. | |
RMR_ERR_NOENDPT | |
The message type in the message buffer did not map to a | |
known endpoint. | |
The following values may be assigned to errno on failure. | |
INVAL | |
Parameter(s) passed to the function were not valid, or the | |
underlying message processing environment was unable to | |
interpret the message. | |
ENOKEY | |
The header information in the message buffer was invalid. | |
ENXIO | |
No known endpoint for the message could be found. | |
EMSGSIZE | |
The underlying transport refused to accept the message | |
because of a size value issue (message was not attempted | |
to be sent). | |
EFAULT | |
The message referenced by the message buffer is corrupt | |
(nil pointer or bad internal length). | |
EBADF | |
Internal RMR error; information provided to the message | |
transport environment was not valid. | |
ENOTSUP | |
Sending was not supported by the underlying message | |
transport. | |
EFSM | |
The device is not in a state that can accept the message. | |
EAGAIN | |
The device is not able to accept a message for sending. | |
The user application should attempt to resend. | |
EINTR | |
The operation was interrupted by delivery of a signal | |
before the message was sent. | |
ETIMEDOUT | |
The underlying message environment timed out during the | |
send process. | |
ETERM | |
The underlying message environment is in a shutdown state. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
The following is a simple example of how the rmr_send_msg | |
function is called. In this example, the send message buffer | |
is saved between calls and reused eliminating alloc/free | |
cycles. | |
:: | |
static rmr_mbuf_t* send_msg = NULL; // message to send; reused on each call | |
msg_t* send_pm; // payload for send | |
msg_t* pm; // our message format in the received payload | |
if( send_msg == NULL ) { | |
send_msg = rmr_alloc_msg( mr, MAX_SIZE ); // new buffer to send | |
} | |
// reference payload and fill in message type | |
pm = (msg_t*) send_msg->payload; | |
send_msg->mtype = MT_ANSWER; | |
msg->len = generate_data( pm ); // something that fills the payload in | |
msg = rmr_send_msg( mr, send_msg ); // ensure new pointer used after send | |
if( ! msg ) { | |
return ERROR; | |
} else { | |
if( msg->state != RMR_OK ) { | |
// check for RMR_ERR_RETRY, and resend if needed | |
// else return error | |
} | |
} | |
return OK; | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_mk_ring(3), | |
rmr_ring_free(3), rmr_torcv_rcv(3), rmr_wh_send_msg(3) |