uta_ctx_t* ctx;
int state;
char* hold_src; // we need the original source if send fails
+ char* hold_ip; // also must hold original ip
int sock_ok = 0; // true if we found a valid endpoint socket
if( (ctx = (uta_ctx_t *) vctx) == NULL || msg == NULL ) { // bad stuff, bail fast
errno = EINVAL; // if msg is null, this is their clue
if( msg != NULL ) {
msg->state = RMR_ERR_BADARG;
+ msg->tp_state = errno;
}
return msg;
}
if( msg->header == NULL ) {
fprintf( stderr, "[ERR] rmr_send_msg: message had no header\n" );
msg->state = RMR_ERR_NOHDR;
+ msg->tp_state = errno;
return msg;
}
((uta_mhdr_t *) msg->header)->flags &= ~HFL_CALL_MSG; // must ensure call flag is off
- if( HDR_VERSION( msg->header ) > 2 ) { // new version uses sender's ip address for rts
- sock_ok = uta_epsock_byname( ctx->rtable, (char *) ((uta_mhdr_t *)msg->header)->srcip, &nn_sock ); // default to IP based rts
- }
+
+ sock_ok = uta_epsock_byname( ctx->rtable, (char *) ((uta_mhdr_t *)msg->header)->src, &nn_sock ); // src is always used first for rts
if( ! sock_ok ) {
- sock_ok = uta_epsock_byname( ctx->rtable, (char *) ((uta_mhdr_t *)msg->header)->src, &nn_sock ); // IP not in rt, try name
+ if( HDR_VERSION( msg->header ) > 2 ) { // with ver2 the ip is there, try if src name not known
+ sock_ok = uta_epsock_byname( ctx->rtable, (char *) ((uta_mhdr_t *)msg->header)->srcip, &nn_sock );
+ }
if( ! sock_ok ) {
msg->state = RMR_ERR_NOENDPT;
return msg; // preallocated msg can be reused since not given back to nn
msg->state = RMR_OK; // ensure it is clear before send
hold_src = strdup( (char *) ((uta_mhdr_t *)msg->header)->src ); // the dest where we're returning the message to
+ hold_ip = strdup( (char *) ((uta_mhdr_t *)msg->header)->srcip ); // both the src host and src ip
strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, ctx->my_name, RMR_MAX_SRC ); // must overlay the source to be ours
msg = send_msg( ctx, msg, nn_sock, -1 );
if( msg ) {
strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, hold_src, RMR_MAX_SRC ); // always return original source so rts can be called again
+ strncpy( (char *) ((uta_mhdr_t *)msg->header)->srcip, hold_ip, RMR_MAX_SRC ); // always return original source so rts can be called again
msg->flags |= MFL_ADDSRC; // if msg given to send() it must add source
}
free( hold_src );
+ free( hold_ip );
return msg;
}
if( msg->state != RMR_ERR_RETRY ) {
msg->state = RMR_ERR_CALLFAILED; // errno not available to all wrappers; don't stomp if marked retry
}
+ msg->tp_state = errno;
return msg;
}
rmr_mbuf_t* qm; // message that was queued on the ring
if( (ctx = (uta_ctx_t *) vctx) == NULL ) {
+ errno = EINVAL;
if( old_msg != NULL ) {
old_msg->state = RMR_ERR_BADARG;
+ old_msg->tp_state = errno;
}
- errno = EINVAL;
return old_msg;
}
errno = 0;
rmr_mbuf_t* msg;
if( (ctx = (uta_ctx_t *) vctx) == NULL ) {
+ errno = EINVAL;
if( old_msg != NULL ) {
old_msg->state = RMR_ERR_BADARG;
+ old_msg->tp_state = errno;
}
- errno = EINVAL;
return old_msg;
}
nready = epoll_wait( eps->ep_fd, eps->events, 1, ms_to ); // block until something or timedout
if( nready <= 0 ) { // we only wait on ours, so we assume ready means it's ours
msg->state = RMR_ERR_TIMEOUT;
+ msg->tp_state = errno;
} else {
return rcv_msg( ctx, msg ); // receive it and return it
}
int exp_len = 0; // length of expected ID
if( (ctx = (uta_ctx_t *) vctx) == NULL ) {
+ errno = EINVAL;
if( msg != NULL ) {
msg->state = RMR_ERR_BADARG;
+ msg->tp_state = errno;
}
- errno = EINVAL;
return msg;
}
char* proto_port;
char wbuf[1024]; // work buffer
char* tok; // pointer at token in a buffer
+ char* tok2;
int state;
if( ! announced ) {
port = proto_port; // assume something like "1234" was passed
}
- if( (gethostname( wbuf, sizeof( wbuf ) )) != 0 ) {
- fprintf( stderr, "[CRI] rmr_init: cannot determine localhost name: %s\n", strerror( errno ) );
- return NULL;
- }
- if( (tok = strchr( wbuf, '.' )) != NULL ) {
- *tok = 0; // we don't keep domain portion
+ if( (tok = getenv( ENV_SRC_ID )) != NULL ) { // env var overrides what we dig from system
+ tok = strdup( tok ); // something we can destroy
+ if( *tok == '[' ) { // we allow an ipv6 address here
+ tok2 = strchr( tok, ']' ) + 1; // we will chop the port (...]:port) if given
+ } else {
+ tok2 = strchr( tok, ':' ); // find :port if there so we can chop
+ }
+ if( tok2 && *tok2 ) { // if it's not the end of string marker
+ *tok2 = 0; // make it so
+ }
+
+ snprintf( wbuf, RMR_MAX_SRC, "%s", tok );
+ free( tok );
+ } else {
+ if( (gethostname( wbuf, sizeof( wbuf ) )) != 0 ) {
+ fprintf( stderr, "[CRI] rmr_init: cannot determine localhost name: %s\n", strerror( errno ) );
+ return NULL;
+ }
+ if( (tok = strchr( wbuf, '.' )) != NULL ) {
+ *tok = 0; // we don't keep domain portion
+ }
}
+
ctx->my_name = (char *) malloc( sizeof( char ) * RMR_MAX_SRC );
if( snprintf( ctx->my_name, RMR_MAX_SRC, "%s:%s", wbuf, port ) >= RMR_MAX_SRC ) { // our registered name is host:port
fprintf( stderr, "[CRI] rmr_init: hostname + port must be less than %d characters; %s:%s is not\n", RMR_MAX_SRC, wbuf, port );
}
if( DEBUG ) fprintf( stderr, "[DBUG] default ip address: %s\n", ctx->my_ip );
+ if( (tok = getenv( ENV_WARNINGS )) != NULL ) {
+ if( *tok == '1' ) {
+ ctx->flags |= CTXFL_WARN; // turn on some warnings (not all, just ones that shouldn't impact performance)
+ }
+ }
if( (interface = getenv( ENV_BIND_IF )) == NULL ) {
errno = EINVAL;
if( mbuf ) {
mbuf->state = RMR_ERR_BADARG;
+ mbuf->tp_state = errno;
}
return mbuf;
}
errno = EINVAL;
if( mbuf != NULL ) {
mbuf->state = RMR_ERR_NOTSUPP;
+ mbuf->tp_state = errno;
}
return mbuf;
}
}
chute = &ctx->chutes[0]; // chute 0 used only for its semaphore
-
+
if( max_wait > 0 ) {
clock_gettime( CLOCK_REALTIME, &ts );
seconds = 1; // use as flag later to invoked timed wait
}
- errno = 0;
- while( chute->mbuf == NULL && ! errno ) {
+ errno = EINTR;
+ state = -1;
+ while( state < 0 && errno == EINTR ) {
if( seconds ) {
state = sem_timedwait( &chute->barrier, &ts ); // wait for msg or timeout
} else {
state = sem_wait( &chute->barrier );
}
-
- if( state < 0 && errno == EINTR ) { // interrupted go back and wait; all other errors cause exit
- errno = 0;
- }
}
if( state < 0 ) {
mbuf = ombuf; // return caller's buffer if they passed one in
} else {
+ errno = 0; // interrupted call state could be left; clear
if( DEBUG ) fprintf( stderr, "[DBUG] mt_rcv extracting from normal ring\n" );
if( (mbuf = (rmr_mbuf_t *) uta_ring_extract( ctx->mring )) != NULL ) { // pop if queued
- if( mbuf ) {
- mbuf->state = RMR_OK;
-
- if( ombuf ) {
- rmr_free_msg( ombuf ); // we cannot reuse as mbufs are queued on the ring
- }
- } else {
- mbuf = ombuf; // no buffer, return user's if there
+ mbuf->state = RMR_OK;
+
+ if( ombuf ) {
+ rmr_free_msg( ombuf ); // we cannot reuse as mbufs are queued on the ring
}
+ } else {
+ errno = ETIMEDOUT;
+ mbuf = ombuf; // no buffer, return user's if there
}
}
+ if( mbuf ) {
+ mbuf->tp_state = errno;
+ }
return mbuf;
}
long nano_sec; // max wait xlated to nano seconds
int state;
+ errno = EINVAL;
if( (ctx = (uta_ctx_t *) vctx) == NULL || mbuf == NULL ) {
- errno = EINVAL;
if( mbuf ) {
+ mbuf->tp_state = errno;
mbuf->state = RMR_ERR_BADARG;
}
return mbuf;
if( ! (ctx->flags & CFL_MTC_ENABLED) ) {
mbuf->state = RMR_ERR_NOTSUPP;
+ mbuf->tp_state = errno;
return mbuf;
}
if( call_id > MAX_CALL_ID || call_id < 2 ) { // 0 and 1 are reserved; user app cannot supply them
mbuf->state = RMR_ERR_BADARG;
+ mbuf->tp_state = errno;
return mbuf;
}
mbuf = mtosend_msg( ctx, mbuf, 0 ); // use internal function so as not to strip call-id; should be nil on success!
if( mbuf ) {
if( mbuf->state != RMR_OK ) {
+ mbuf->tp_state = errno;
return mbuf; // timeout or unable to connect or no endpoint are most likely issues
}
}
+ state = 0;
errno = 0;
while( chute->mbuf == NULL && ! errno ) {
if( seconds ) {