msg->xaction = ((uta_mhdr_t *)msg->header)->xid; // point at transaction id in header area
msg->state = state; // fill in caller's state (likely the state of the last operation)
msg->flags |= MFL_ZEROCOPY; // this is a zerocopy sendable message
- strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, ctx->my_name, RMR_MAX_SID );
+ strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, ctx->my_name, RMR_MAX_SRC );
+ strncpy( (char *) ((uta_mhdr_t *)msg->header)->srcip, ctx->my_ip, RMR_MAX_SRC );
if( DEBUG > 1 ) fprintf( stderr, "[DBUG] alloc_zcmsg mlen=%ld size=%d mpl=%d flags=%02x\n", (long) mlen, size, ctx->max_plen, msg->flags );
is somewhat based on header version.
*/
static void ref_tpbuf( rmr_mbuf_t* msg, size_t alen ) {
- uta_mhdr_t* hdr; // current header
+ uta_mhdr_t* hdr = NULL; // current header
uta_v1mhdr_t* v1hdr; // version 1 header
int ver;
int hlen; // header len to use for a truncation check
break;
}
- if( msg->len > (msg->alloc_len - hlen ) ) { // more than we should have had room for; error
+ if( msg->len > (msg->alloc_len - hlen ) ) {
msg->state = RMR_ERR_TRUNC;
msg->len = msg->alloc_len - hlen; // adjust len down so user app doesn't overrun
} else {
reuse. They have their reasons I guess. Thus, we will free
the old transport buffer if user passes the message in; at least
our mbuf will be reused.
+
+ When msg->state is not ok, this function must set tp_state in the message as some API
+ fucntions return the message directly and do not propigate errno into the message.
*/
static rmr_mbuf_t* rcv_msg( uta_ctx_t* ctx, rmr_mbuf_t* old_msg ) {
int state;
msg->state = nng_recvmsg( ctx->nn_sock, (nng_msg **) &msg->tp_buf, NO_FLAGS ); // blocks hard until received
if( (msg->state = xlate_nng_state( msg->state, RMR_ERR_RCVFAILED )) != RMR_OK ) {
+ msg->tp_state = errno;
return msg;
}
+ msg->tp_state = 0;
if( msg->tp_buf == NULL ) { // if state is good this _should_ not be nil, but parninoia says check anyway
msg->state = RMR_ERR_EMPTY;
+ msg->tp_state = 0;
return msg;
}
msg->mtype, msg->state, msg->len, msg->payload - (unsigned char *) msg->header );
} else {
msg->state = RMR_ERR_EMPTY;
+ msg->tp_state = 0;
msg->len = 0;
msg->alloc_len = rsize;
msg->payload = NULL;
Called by rmr_send_msg() and rmr_rts_msg(), etc. and thus we assume that all pointer
validation has been done prior.
+
+ When msg->state is not ok, this function must set tp_state in the message as some API
+ fucntions return the message directly and do not propigate errno into the message.
*/
static rmr_mbuf_t* send_msg( uta_ctx_t* ctx, rmr_mbuf_t* msg, nng_socket nn_sock, int retries ) {
int state;
uta_mhdr_t* hdr;
int nng_flags = NNG_FLAG_NONBLOCK; // if we need to set any nng flags (zc buffer) add it to this
- int spin_retries = 1000; // if eagain/timeout we'll spin this many times before giving up the CPU
+ int spin_retries = 1000; // if eagain/timeout we'll spin, at max, this many times before giving up the CPU
int tr_len; // trace len in sending message so we alloc new message with same trace size
// future: ensure that application did not overrun the XID buffer; last byte must be 0
tr_len = RMR_TR_LEN( hdr ); // snarf trace len before sending as hdr is invalid after send
if( msg->flags & MFL_ADDSRC ) { // buffer was allocated as a receive buffer; must add our source
- strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, ctx->my_name, RMR_MAX_SID ); // must overlay the source to be ours
+ strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, ctx->my_name, RMR_MAX_SRC ); // must overlay the source to be ours
+ strncpy( (char *) ((uta_mhdr_t *)msg->header)->srcip, ctx->my_ip, RMR_MAX_SRC );
}
errno = 0;
if( retries > 0 && (state == NNG_EAGAIN || state == NNG_ETIMEDOUT) ) {
if( --spin_retries <= 0 ) { // don't give up the processor if we don't have to
retries--;
- usleep( 1 ); // sigh, give up the cpu and hope it's just 1 miscrosec
+ if( retries > 0 ) { // only if we'll loop through again
+ usleep( 1 ); // sigh, give up the cpu and hope it's just 1 miscrosec
+ }
spin_retries = 1000;
}
} else {
// future: this should not happen as all buffers we deal with are zc buffers; might make sense to remove the test and else
msg->state = RMR_ERR_SENDFAILED;
errno = ENOTSUP;
+ msg->tp_state = errno;
return msg;
/*
NOT SUPPORTED
message type is used. If the initial lookup, with a subid, fails, then a
second lookup using just the mtype is tried.
+ When msg->state is not OK, this function must set tp_state in the message as
+ some API fucntions return the message directly and do not propigate errno into
+ the message.
+
CAUTION: this is a non-blocking send. If the message cannot be sent, then
it will return with an error and errno set to eagain. If the send is
a limited fanout, then the returned status is the status of the last
if( msg != NULL ) {
msg->state = RMR_ERR_BADARG;
errno = EINVAL; // must ensure it's not eagain
+ msg->tp_state = errno;
}
return msg;
}
fprintf( stderr, "rmr_send_msg: ERROR: message had no header\n" );
msg->state = RMR_ERR_NOHDR;
errno = EBADMSG; // must ensure it's not eagain
+ msg->tp_state = errno;
return msg;
}
msg->state = RMR_ERR_NOENDPT;
errno = ENXIO; // must ensure it's not eagain
+ msg->tp_state = errno;
return msg; // caller can resend (maybe) or free
}