enhance(API): Add source IP support to msg header 50/250/6
authorE. Scott Daniels <daniels@research.att.com>
Mon, 3 Jun 2019 19:45:12 +0000 (19:45 +0000)
committerE. Scott Daniels <daniels@research.att.com>
Wed, 5 Jun 2019 12:52:52 +0000 (12:52 +0000)
The message header now carries both the hostname and IP
address of the source process.  The return to sender function
will use the IP address instead of the host name. It is possible
to set RMR_SRC_NAMEONLY=1 in the environment, or for the user
application to set this flag, to force only the use of the
hostname in the header.

Signed-off-by: E. Scott Daniels <daniels@research.att.com>
Change-Id: Id6305fab79fabbffffb343af1094e48fbf662b5d
Signed-off-by: E. Scott Daniels <daniels@research.att.com>
27 files changed:
CMakeLists.txt
doc/CMakeLists.txt
doc/src/man/rmr.7.xfm
doc/src/man/rmr_get_meid.3.xfm
doc/src/man/rmr_get_src.3.xfm
src/rmr/common/include/rmr.h
src/rmr/common/include/rmr_agnostic.h
src/rmr/common/src/mbuf_api.c
src/rmr/common/src/tools_static.c
src/rmr/nanomsg/include/rmr_private.h
src/rmr/nanomsg/src/rmr.c
src/rmr/nanomsg/src/sr_static.c
src/rmr/nng/include/rmr_nng_private.h
src/rmr/nng/src/rmr_nng.c
src/rmr/nng/src/sr_nng_static.c
test/app_test/run_all.ksh
test/mbuf_api_static_test.c
test/mbuf_api_test.c
test/rmr_nng_api_static_test.c
test/rmr_nng_test.c
test/sr_nano_static_test.c
test/sr_nng_static_test.c
test/test_nng_em.c
test/test_support.c
test/tools_static_test.c
test/tools_test.c
test/wormhole_static_test.c

index b30c364..05385a5 100644 (file)
@@ -23,7 +23,7 @@ cmake_minimum_required( VERSION 3.5 )
 
 set( major_version "1" )               # should be automatically populated from git tag later, but until CI process sets a tag we use this
 set( minor_version "0" )
-set( patch_level "27" )
+set( patch_level "28" )
 
 set( install_root "${CMAKE_INSTALL_PREFIX}" )
 set( install_lib "lib" )
index b092fdc..7675bdc 100644 (file)
@@ -82,6 +82,7 @@ if( BUILD_DOC )
                rmr_get_src.3
                rmr_mt_call.3
                rmr_mt_rcv.3
+               rmr_get_srcip.3
        )
 
        # empty list of roff/troff input files we generated
index 2ff5e6c..affdf24 100644 (file)
@@ -119,6 +119,7 @@ rmr_free_msg(3),
 rmr_init(3),
 rmr_init_trace(3),
 rmr_get_src(3),
+rmr_get_srcip(3),
 rmr_get_trace(3),
 rmr_get_trlen(3),
 rmr_payload_size(3),
index 7f095c9..427fbd6 100644 (file)
@@ -78,7 +78,7 @@ the following with the indicated meaning.
 &half_space
 &di(ENOMEM) A nil pointer was passed for &ital( dest, ) however it was not possible to allocate a 
        buffer using malloc().
-&end_dilist
+&end_dlist
 
 
 
index 5ea92f3..42146e8 100644 (file)
@@ -78,7 +78,7 @@ the following with the indicated meaning.
 &beg_dlist(.75i : ^&bold_font )
 &half_space
 &di(EINVAL) The message, or an internal portion of the message, was corrupted or the pointer was invalid.
-&end_dilist
+&end_dlist
 
 
 
@@ -90,6 +90,7 @@ rmr_bytes2meid(3),
 rmr_call(3),
 rmr_free_msg(3),
 rmr_get_rcvfd(3),
+rmr_get_srcip(3),
 rmr_payload_size(3),
 rmr_send_msg(3),
 rmr_rcv_msg(3),
index bed5f2a..eb24e55 100644 (file)
@@ -36,9 +36,9 @@ extern "C" {
 
 
 #define RMR_MAX_XID                    32              // space in header reserved for user xaction id
-#define RMR_MAX_SID                    32              // spece in header reserved for sender id
 #define RMR_MAX_MEID           32              // spece in header reserved for managed element id
 #define RMR_MAX_SRC                    64              // max length of hostname (which could be IPv6 addr with [...]:port so more than the 39 bytes of a plain addr
+#define RMR_MAX_SID                    32              // misc sender info/data (reserved)
 #define RMR_MAX_RCV_BYTES      4096    // max bytes we support in a receive message
 
                                                                        // various flags for function calls
@@ -46,6 +46,7 @@ extern "C" {
 #define RMRFL_NOTHREAD         0x01    // do not start an additional route collector thread
 #define RMRFL_MTCALL           0x02    // set up multi-threaded call support (rmr_init)
 #define RMRFL_AUTO_ALLOC       0x03    // send auto allocates a zerocopy buffer
+#define RMRFL_NAME_ONLY                0x04    // only the hostname:ip is provided as source information for rts() calls
 
 #define RMR_DEF_SIZE           0               // pass as size to have msg allocation use the default msg size
 
@@ -131,6 +132,7 @@ extern int rmr_bytes2xact( rmr_mbuf_t* mbuf, unsigned char const* src, int len )
 extern void rmr_free_msg( rmr_mbuf_t* mbuf );
 extern unsigned char*  rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest );
 extern unsigned char*  rmr_get_src( rmr_mbuf_t* mbuf, unsigned char* dest );
+extern unsigned char* rmr_get_srcip( rmr_mbuf_t* msg, unsigned char* dest );
 extern rmr_mbuf_t* rmr_realloc_msg( rmr_mbuf_t* mbuf, int new_tr_size );
 extern int rmr_str2meid( rmr_mbuf_t* mbuf, unsigned char const* str );
 extern void rmr_str2payload( rmr_mbuf_t* mbuf, unsigned char const* str );
index c037900..465f60a 100644 (file)
@@ -44,14 +44,15 @@ typedef struct uta_ctx  uta_ctx_t;
 #define QUOTE_DEF(a) QUOTE(a)  // allow a #define value to be quoted (e.g. QUOTE(MAJOR_VERSION) )
 
 
-#define RMR_MSG_VER    2                       // message version this code was designed to handle
+#define RMR_MSG_VER    3                       // message version this code was designed to handle
 
-                                                                       // environment variable names we'll suss out
-#define ENV_BIND_IF "RMR_BIND_IF"      // the interface to bind to for both normal comma and RTG (0.0.0.0 if missing)
-#define ENV_RTG_PORT "RMR_RTG_SVC"     // the port we'll listen on for rtg connections
-#define ENV_SEED_RT    "RMR_SEED_RT"   // where we expect to find the name of the seed route table
-#define ENV_RTG_RAW "RMR_RTG_ISRAW"    // if > 0 we expect route table gen messages as raw (not sent from an RMr application)
+                                                                                       // environment variable names we'll suss out
+#define ENV_BIND_IF "RMR_BIND_IF"                      // the interface to bind to for both normal comma and RTG (0.0.0.0 if missing)
+#define ENV_RTG_PORT "RMR_RTG_SVC"                     // the port we'll listen on for rtg connections
+#define ENV_SEED_RT    "RMR_SEED_RT"                   // where we expect to find the name of the seed route table
+#define ENV_RTG_RAW "RMR_RTG_ISRAW"                    // if > 0 we expect route table gen messages as raw (not sent from an RMr application)
 #define ENV_VERBOSE_FILE "RMR_VCTL_FILE"       // file where vlevel may be managed for some (non-time critical) functions
+#define ENV_NAME_ONLY "RMR_SRC_NAMEONLY"       // src in message is name only
 
 #define NO_FLAGS       0                               // no flags to pass to a function
 
@@ -102,6 +103,8 @@ typedef struct uta_ctx  uta_ctx_t;
 #define SET_HDR_D1_LEN(h,l)    (((uta_mhdr_t *)h)->len2=htonl((int32_t)l))
 #define SET_HDR_D2_LEN(h,l)    (((uta_mhdr_t *)h)->len3=htonl((int32_t)l))
 
+#define HDR_VERSION(h) htonl((((uta_mhdr_t *)h)->rmr_ver))
+
                                                        // index of things in the d1 data space
 #define D1_CALLID_IDX  0       // the call-id to match on return
 
@@ -147,6 +150,9 @@ typedef struct {
        int32_t len2;                                           // length of data 1 (d1)
        int32_t len3;                                           // length of data 2 (d2)
        int32_t sub_id;                                         // subscription id (-1 invalid)
+
+                                                                               // v3 extension
+       unsigned char srcip[RMR_MAX_SRC];       // ip address and port of the source
 } uta_mhdr_t;
 
 
@@ -155,7 +161,7 @@ typedef struct {                                            // old (inflexible) v1 header
        int32_t plen;                                           // payload length
        int32_t rmr_ver;                                        // our internal message version number
        unsigned char xid[RMR_MAX_XID];         // space for user transaction id or somesuch
-       unsigned char sid[RMR_MAX_SID];         // sender ID for return to sender needs
+       unsigned char sid[RMR_MAX_SID];         // misc sender info/data
        unsigned char src[16];                          // name of the sender (source) (old size was 16)
        unsigned char meid[RMR_MAX_MEID];       // managed element id.
        struct timespec ts;                                     // timestamp ???
@@ -242,6 +248,7 @@ static int uta_tokenise( char* buf, char** tokens, int max, char sep );
 static char* uta_h2ip( char const* hname );
 static int uta_lookup_rtg( uta_ctx_t* ctx );
 static int uta_has_str( char const* buf, char const* str, char sep, int max );
+static char* get_default_ip( if_addrs_t* iplist );
 
 // --- message ring --------------------------
 static void* uta_mk_ring( int size );
index 65979de..6d9042a 100644 (file)
@@ -347,3 +347,33 @@ extern unsigned char* rmr_get_src( rmr_mbuf_t* msg, unsigned char* dest ) {
 
        return dest;
 }
+
+/*
+       Returns the string with the IP address as reported by the sender. This is
+       the IP address that the sender has sussed off of one of the interfaces
+       and cannot be guarenteed to be the acutal IP address which was used to 
+       establish the connection.   The caller must provide a buffer of at least
+       64 bytes; the string will be nil terminated. A pointer to the user's buffer
+       is returned on success, nil on failure.
+*/
+extern unsigned char* rmr_get_srcip( rmr_mbuf_t* msg, unsigned char* dest ) {
+       uta_mhdr_t*     hdr = NULL;
+       char*   rstr = NULL;
+
+       errno = EINVAL;
+
+       if( dest != NULL && msg != NULL ) {
+               hdr = msg->header;
+               if( HDR_VERSION( msg->header ) > 2 ) {          // src ip was not present in hdr until ver 3
+                       errno = 0;
+                       strcpy( dest, hdr->srcip );
+                       rstr = dest;
+               } else  {
+                       errno = 0;
+                       strcpy( dest, hdr->src );                               // reutrn the name:port for old messages
+                       rstr = dest;
+               }
+       }
+
+       return rstr;
+}
index 8e615af..67adc85 100644 (file)
@@ -237,9 +237,12 @@ static int uta_has_str( char const* buf, char const* str, char sep, int max ) {
        that could be in the route table.
 
        If the environment variable which limits the binding of our listen port
-       to a single interface (ENV_BIND_IF) then ONLY that address is added to
-       the list so that we don't pick up entries from the rtable that are for other
+       to a single interface (ENV_BIND_IF) then ONLY that interface/address is added
+       to the list so that we don't pick up entries from the rtable that are for other
        processes listening on different interfaces.
+
+       The ENV_BIN_IF environment variable may be either an IP address (v6 must be in 
+       square braces), or an interface name (e.g. eth0).
 */
 if_addrs_t*  mk_ip_list( char* port ) {
        if_addrs_t* l;
@@ -249,7 +252,8 @@ if_addrs_t*  mk_ip_list( char* port ) {
        char    wbuf[NI_MAXHOST+128];
        char*   fmt;
        char*   envp;                           // at the environment var if there
-
+       char*   target_if = NULL;       // target interface supplied by ENV_BIND_IF
+       char*   tok;
 
 
        if( (l = (if_addrs_t *) malloc( sizeof( if_addrs_t ) )) == NULL ) {
@@ -263,18 +267,23 @@ if_addrs_t*  mk_ip_list( char* port ) {
        }
 
        if( (envp = getenv( ENV_BIND_IF )) != NULL ) {
-               snprintf( wbuf, sizeof( wbuf ), "%s:%s", envp, port );          // smash port onto the addr as is
-               l->addrs[l->naddrs] = strdup( wbuf );
-               l->naddrs++;
-               if( DEBUG ) fprintf( stderr, "[INFO] rmr: using only specific bind interface when searching specific RT entries: %s\n", wbuf );
-               return l;
+               if( isdigit( *envp ) || *envp == '[' ) {                                        // ip address given and not device name
+                       snprintf( wbuf, sizeof( wbuf ), "%s:%s", envp, port );          // smash port onto the addr as is
+                       l->addrs[l->naddrs] = strdup( wbuf );
+                       l->naddrs++;
+                       if( DEBUG ) fprintf( stderr, "[INFO] rmr: using only specific bind interface when searching specific RT entries: %s\n", wbuf );
+                       return l;
+               }
+
+               target_if = envp;               // device name given, suss it out below
        }
 
        getifaddrs( &ifs );
        for( ele = ifs; ele; ele = ele->ifa_next ) {
-               *octs = 0;
+               memset( octs, 0, sizeof( octs ) );
+               if( ele && strcmp( ele->ifa_name, "lo" ) &&                                                                     // do NOT capture the loopback interface address
+                       (target_if == NULL || strcmp( ele->ifa_name, target_if ) == 0 ) ) {             // no target, or matches ENV_BIND_IF target
 
-               if( ele && strcmp( ele->ifa_name, "lo" )  ) {
                        if( ele->ifa_addr->sa_family == AF_INET ) {
                                getnameinfo( ele->ifa_addr, sizeof( struct sockaddr_in ),  octs, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
                                fmt = "%s:%s";
@@ -286,7 +295,12 @@ if_addrs_t*  mk_ip_list( char* port ) {
                        }
 
                        if( *octs ) {
+                               if( (tok = strchr( octs, '%' )) != NULL ) {                     // for unknown reasons some ip6 addrs have %if-name appended; truncate
+                                       *tok = 0;
+                               }
                                if( l->naddrs < 128 ) {
+                                       if( DEBUG ) fprintf( stderr, "[DBUG] capture address: %s: %s\n", ele->ifa_name, octs );
+
                                        snprintf( wbuf, sizeof( wbuf ), fmt, octs, port );              // smash port onto the addr
                                        l->addrs[l->naddrs] = strdup( wbuf );
                                        l->naddrs++;
@@ -380,4 +394,21 @@ static int has_myip( char const* buf, if_addrs_t* list, char sep, int max ) {
        return rc;
 }
 
+/*
+       Given a list manager block, return the default IP address.
+       For now, that is just the first address on the list which
+       easily could be non-deterministic and change with each restart
+       of the application if a specific interface is not provided via
+       the environment variable (ENV_BIND_IF) and if there is more than
+       one device available on the container/physical host.
+*/
+static char* get_default_ip( if_addrs_t* iplist ) {
+
+       if( iplist != NULL  &&  iplist->naddrs > 0  &&  iplist->addrs != NULL ) {
+               return strdup( iplist->addrs[0] );
+       }
+
+       return NULL;
+}
+
 #endif
index 8e60d63..8d5d6d6 100644 (file)
@@ -54,6 +54,7 @@ struct endpoint {
 */
 struct uta_ctx {
        char*   my_name;                        // dns name of this host to set in sender field of a message
+       char*   my_ip;                          // default IP address
        int             shutdown;                       // threads should exit if this is set
        int max_mlen;                           // max message length payload+header
        int     max_plen;                               // max payload length
index 93e4f7a..128039d 100644 (file)
@@ -340,11 +340,12 @@ extern rmr_mbuf_t* rmr_send_msg( void* vctx, rmr_mbuf_t* msg ) {
                The caller must check for this and handle.
 */
 extern rmr_mbuf_t*  rmr_rts_msg( void* vctx, rmr_mbuf_t* msg ) {
-       int nn_sock;                            // endpoint socket for send
+       int nn_sock = -1;                       // endpoint socket for send
        uta_ctx_t*      ctx;
        int state;
        uta_mhdr_t*     hdr;
        char*   hold_src;                       // we need the original source if send fails
+       char*   hold_ip;
 
        if( (ctx = (uta_ctx_t *) vctx) == NULL || msg == NULL ) {               // bad stuff, bail fast
                errno = EINVAL;                                                                                         // if msg is null, this is their clue
@@ -361,21 +362,31 @@ extern rmr_mbuf_t*  rmr_rts_msg( void* vctx, rmr_mbuf_t* msg ) {
                return msg;
        }
 
-       nn_sock = uta_epsock_byname( ctx->rtable, (char *) ((uta_mhdr_t *)msg->header)->src );                  // socket of specific endpoint
-       if( nn_sock < 0 ) {
-               msg->state = RMR_ERR_NOENDPT;
-               return msg;                                                     // preallocated msg can be reused since not given back to nn
+       if( HDR_VERSION( msg->header ) > 2 ) {                                                  // new version uses sender's ip address for rts
+               nn_sock = uta_epsock_byname( ctx->rtable, (char *) ((uta_mhdr_t *)msg->header)->srcip );                // socket of specific endpoint
+       }
+       if(  nn_sock < 0 ) {
+               nn_sock = uta_epsock_byname( ctx->rtable, (char *) ((uta_mhdr_t *)msg->header)->src );                  // socket of specific endpoint
+               if(  nn_sock < 0 ) {
+                       msg->state = RMR_ERR_NOENDPT;
+                       return msg;                                                                                                                             // preallocated msg can be reused since not given back to nn
+               }
        }
 
        hold_src = strdup( (char *) ((uta_mhdr_t *)msg->header)->src );                                                 // the dest where we're returning the message to
-       strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, ctx->my_name, RMR_MAX_SID );                // must overlay the source to be ours
+       hold_ip = strdup( (char *) ((uta_mhdr_t *)msg->header)->srcip );
+       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 );
+
        msg = send_msg( ctx, msg, nn_sock );
        if( msg ) {
-               strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, hold_src, RMR_MAX_SID );            // always return original source so rts can be called again
+               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 );
                msg->flags |= MFL_ADDSRC;                                                                                                       // if msg given to send() it must add source
        }
 
        free( hold_src );
+       free( hold_ip );
        return msg;
 }
 
@@ -620,9 +631,9 @@ static void* init( char* uproto_port, int max_msg_size, int flags ) {
        if( (tok = strchr( wbuf, '.' )) != NULL ) {
                *tok = 0;                                                                       // we don't keep domain portion
        }
-       ctx->my_name = (char *) malloc( sizeof( char ) * RMR_MAX_SID );
-       if( snprintf( ctx->my_name, RMR_MAX_SID, "%s:%s", wbuf, port ) >= RMR_MAX_SID ) {                       // our registered name is host:port
-               fprintf( stderr, "[CRIT] rmr_init: hostname + port must be less than %d characters; %s:%s is not\n", RMR_MAX_SID, wbuf, port );
+       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, "[CRIT] rmr_init: hostname + port must be less than %d characters; %s:%s is not\n", RMR_MAX_SRC, wbuf, port );
                return NULL;
        }
 
@@ -637,6 +648,26 @@ static void* init( char* uproto_port, int max_msg_size, int flags ) {
                return NULL;
        }
 
+       if( (tok = getenv( ENV_NAME_ONLY )) != NULL ) {
+               if( atoi( tok ) > 0 ) {
+                       flags |= RMRFL_NAME_ONLY;                                       // don't allow IP addreess to go out in messages
+               }
+       }
+
+       if( flags & RMRFL_NAME_ONLY ) {
+               ctx->my_ip = strdup( ctx->my_name );                            // user application or env var has specified that IP address is NOT sent out, use name
+               if( DEBUG ) fprintf( stderr, "[DBUG] name only mode is set; not sending IP address as source\n" );
+       } else {
+               ctx->ip_list = mk_ip_list( port );                              // suss out all IP addresses we can find on the box, and bang on our port for RT comparisons
+               ctx->my_ip = get_default_ip( ctx->ip_list );    // and (guess) at what should be the default to put into messages as src
+               if( ctx->my_ip == NULL ) {
+                       strcpy( ctx->my_ip, ctx->my_name );                     // revert to name if we cant suss out ip address
+                       fprintf( stderr, "[WARN] rmr_init: default ip address could not be sussed out, using name as source\n" );
+               } else {
+                       if( DEBUG ) fprintf( stderr, "[DBUG] default ip address: %s\n", ctx->my_ip );
+               }
+       }
+
        if( ! (flags & FL_NOTHREAD) ) {                 // skip if internal context that does not need rout table thread
                if( pthread_create( &ctx->rtc_th,  NULL, rtc, (void *) ctx ) ) {                // kick the rt collector thread
                        fprintf( stderr, "[WARN] rmr_init: unable to start route table collector thread: %s", strerror( errno ) );
index 18acdda..53eb5d9 100644 (file)
@@ -116,7 +116,8 @@ static rmr_mbuf_t* alloc_zcmsg( uta_ctx_t* ctx, rmr_mbuf_t* msg, int size, int s
        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 = %d size=%d mpl=%d flags=%02x %p m=%p @%p\n", mlen, size, ctx->max_plen, msg->flags, &msg->flags, msg, msg->header );
 
@@ -334,7 +335,8 @@ static rmr_mbuf_t* send_msg( uta_ctx_t* ctx, rmr_mbuf_t* msg, int nn_sock ) {
        hdr->plen = htonl( msg->len );
 
        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 );
        }
 
        tr_len = RMR_TR_LEN( hdr );
index 2349ce6..4933f8b 100644 (file)
@@ -65,6 +65,7 @@ typedef struct epoll_stuff {
 */
 struct uta_ctx {
        char*   my_name;                        // dns name of this host to set in sender field of a message
+       char*   my_ip;                          // the ip address we _think_ we are using sent in src_ip of the message for rts
        int     shutdown;                               // thread notification if we need to tell them to stop
        int max_mlen;                           // max message length payload+header
        int     max_plen;                               // max payload length
index 77f539e..8a91544 100644 (file)
@@ -248,7 +248,7 @@ extern rmr_mbuf_t*  rmr_rts_msg( void* vctx, rmr_mbuf_t* msg ) {
        uta_ctx_t*      ctx;
        int                     state;
        char*           hold_src;                       // we need the original source if send fails
-       int                     sock_ok;                        // true if we found a valid endpoint socket
+       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
@@ -266,18 +266,23 @@ extern rmr_mbuf_t*  rmr_rts_msg( void* vctx, rmr_mbuf_t* msg ) {
        }
 
        ((uta_mhdr_t *) msg->header)->flags &= ~HFL_CALL_MSG;                   // must ensure call flag is off
-       sock_ok = uta_epsock_byname( ctx->rtable, (char *) ((uta_mhdr_t *)msg->header)->src, &nn_sock );                        // socket of specific endpoint
+       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
+       }
        if( ! sock_ok ) {
-               msg->state = RMR_ERR_NOENDPT;
-               return msg;                                                     // preallocated msg can be reused since not given back to nn
+               sock_ok = uta_epsock_byname( ctx->rtable, (char *) ((uta_mhdr_t *)msg->header)->src, &nn_sock );                // IP  not in rt, try name
+               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
-       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
        msg = send_msg( ctx, msg, nn_sock, -1 );
        if( msg ) {
-               strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, hold_src, RMR_MAX_SID );    // always return original source so rts can be called again
+               strncpy( (char *) ((uta_mhdr_t *)msg->header)->src, hold_src, 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
        }
 
@@ -641,13 +646,29 @@ static void* init(  char* uproto_port, int max_msg_size, int flags ) {
        if( (tok = strchr( wbuf, '.' )) != NULL ) {
                *tok = 0;                                                                       // we don't keep domain portion
        }
-       ctx->my_name = (char *) malloc( sizeof( char ) * RMR_MAX_SID );
-       if( snprintf( ctx->my_name, RMR_MAX_SID, "%s:%s", wbuf, port ) >= RMR_MAX_SID ) {                       // 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_SID, wbuf, port );
+       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 );
                return NULL;
        }
 
-       ctx->ip_list = mk_ip_list( port );              // suss out all IP addresses we can find on the box, and bang on our port for RT comparisons
+       if( (tok = getenv( ENV_NAME_ONLY )) != NULL ) {
+               if( atoi( tok ) > 0 ) {
+                       flags |= RMRFL_NAME_ONLY;                                       // don't allow IP addreess to go out in messages
+               }
+       }
+
+       ctx->ip_list = mk_ip_list( port );                              // suss out all IP addresses we can find on the box, and bang on our port for RT comparisons
+       if( flags & RMRFL_NAME_ONLY ) {
+               ctx->my_ip = strdup( ctx->my_name );                    // user application or env var has specified that IP address is NOT sent out, use name
+       } else {
+               ctx->my_ip = get_default_ip( ctx->ip_list );    // and (guess) at what should be the default to put into messages as src
+               if( ctx->my_ip == NULL ) {
+                       fprintf( stderr, "[WARN] rmr_init: default ip address could not be sussed out, using name\n" );
+                       strcpy( ctx->my_ip, ctx->my_name );                     // if we cannot suss it out, use the name rather than a nil pointer
+               }
+       }
+       if( DEBUG ) fprintf( stderr, "[DBUG] default ip address: %s\n", ctx->my_ip );
 
 
 
index da4dfbd..b7fa3f2 100644 (file)
@@ -153,7 +153,8 @@ static rmr_mbuf_t* alloc_zcmsg( uta_ctx_t* ctx, rmr_mbuf_t* msg, int size, int s
        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 );
 
@@ -206,7 +207,7 @@ static rmr_mbuf_t* alloc_mbuf( uta_ctx_t* ctx, int state ) {
        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
@@ -249,7 +250,7 @@ static void ref_tpbuf( rmr_mbuf_t* msg, size_t alen )  {
                        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 {
@@ -525,7 +526,8 @@ static rmr_mbuf_t* send_msg( uta_ctx_t* ctx, rmr_mbuf_t* msg, nng_socket nn_sock
        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;
index f2260ae..ffcd3e1 100644 (file)
@@ -1,7 +1,21 @@
 
-# run all of the tests, building rmr before the first one.
+# run all of the tests, building rmr before the first one if -B is on the command line.
+
+build=""
+
+while [[ $1 == "-"* ]]
+do
+       case $1 in 
+               -B)     build="-B";;
+
+               *)      echo "'$1' is not a recognised option and is ignored";;
+       esac
+
+       shift
+done
+
 set -e
-ksh run_app_test.ksh -B
+ksh run_app_test.ksh $build
 ksh run_multi_test.ksh
 ksh run_rr_test.ksh
 ksh run_rts_test.ksh -s 20
index 99452dc..8b17968 100644 (file)
@@ -264,8 +264,19 @@ int mbuf_api_test( ) {
        errors += fail_not_nil( buf, "rmr_get_src returned a pointer when given a nil dest buffer" );
 
        buf = rmr_get_src( mbuf, src_buf );
-       errors += fail_not_equal( (int) buf, (int) src_buf, "rmr_get_src didn't return expexted buffer pointer" );
+       errors += fail_not_equalp( buf, src_buf, "rmr_get_src didn't return expexted buffer pointer" );
 
+       buf = rmr_get_srcip( NULL, NULL );
+       errors += fail_not_nil( buf, "get_srcip did not return nil when given nil pointers" );
+
+       buf = rmr_get_srcip( mbuf, NULL );
+       errors += fail_not_nil( buf, "get_srcip did not return nil when given nil destination" );
+
+       buf = rmr_get_srcip( mbuf, src_buf );
+       errors += fail_not_equalp( buf, src_buf, "rmr_get_srcip didn't return expexted buffer pointer" );
+
+       test_set_ver( mbuf, 2 );                                                        // set older message version to ensure properly handled
+       buf = rmr_get_srcip( mbuf, src_buf );
 
        return errors > 0;                      // overall exit code bad if errors
 }
index 796888f..09c4da4 100644 (file)
@@ -48,6 +48,7 @@
 
 #include "mbuf_api.c"
 
+#define MSG_VER 3
 #include "test_support.c"                                              // our private library of test tools
 #include "mbuf_api_static_test.c"                              // test functions
 
index 0cb49a5..a3c8350 100644 (file)
@@ -116,6 +116,7 @@ static int rmr_api_test( ) {
        v = rmr_ready( NULL );
        errors += fail_if( v != 0, "rmr_ready returned true before initialisation "  );
 
+       em_set_long_hostname( 1 );
        if( (rmc = rmr_init( "4560", 1024, FL_NOTHREAD )) == NULL ) {
                fail_if_nil( rmc, "rmr_init returned a nil pointer "  );
                return 1;
@@ -137,8 +138,15 @@ static int rmr_api_test( ) {
        msg = rmr_alloc_msg( NULL,  1024 );                                                                     // should return nil pointer
        errors += fail_not_nil( msg, "rmr_alloc_msg didn't return nil when given nil context "  );
 
+       
        msg = rmr_alloc_msg( rmc, 2048 );                               // allocate larger than default size given on init
        errors += fail_if_nil( msg, "rmr_alloc_msg returned nil msg pointer "  );
+       if( msg ) {
+               rmr_get_srcip( msg, wbuf );
+               errors += fail_if_equal( 0, strlen( wbuf ), "rmr_get_srcip did not did not return string with length (b) after alloc_msg" );
+               fprintf( stderr, "<INFO> ip: %s\n", wbuf );
+       }
+
 
        v = rmr_payload_size( NULL );
        errors += fail_if( v >= 0, "rmr_payload_size returned valid size for nil message "  );
@@ -215,7 +223,6 @@ static int rmr_api_test( ) {
                if( msg2->state != RMR_ERR_EMPTY ) {
                        errors += fail_not_equal( msg2->state, RMR_OK, "receive given nil message did not return msg with good state (not empty) "  );
                }
-               //errors += fail_not_equal( msg2->state, RMR_OK, "receive given nil message did not return msg with good state "  );
        }
 
 
@@ -233,12 +240,17 @@ static int rmr_api_test( ) {
 
        msg->state = 0;
        msg = rmr_rts_msg( NULL, msg );                 // should set state in msg
-       errors += fail_if_equal( msg->state, 0, "rmr_rts_msg did not set state when given valid message but no context "  );
+       if( msg ) {
+               errors += fail_if_equal( msg->state, 0, "rmr_rts_msg did not set state when given valid message but no context "  );
+       } else {
+               errors += fail_if_nil( msg,  "rmr_rts_msg returned a nil msg when given a good one" );
+       }
 
 
        msg = rmr_rts_msg( rmc, msg );                  // return the buffer to the sender
        errors += fail_if_nil( msg, "rmr_rts_msg did not return a message pointer "  );
-       errors += fail_if( errno != 0, "rmr_rts_msg did not reset errno "  );
+       errors += fail_not_equal( msg->state, 0, "rts_msg did not return a good state (a) when expected" );
+       errors += fail_not_equal( errno, 0, "rmr_rts_msg did not reset errno (a) expected (b)"  );
 
 
 
index 1a8df89..c9d9a6a 100644 (file)
@@ -114,6 +114,10 @@ int main() {
 
        fprintf( stderr, "<INFO> starting RMr API tests\n" );
        errors += rmr_api_test();
+
+       fprintf( stderr, "<INFO> run RMr API tests with src name only env var set\n" );
+       setenv( "RMR_SRC_NAMEONLY", "1", 1 );
+       errors += rmr_api_test();
        fprintf( stderr, "<INFO> error count: %d\n", errors );
 
        fprintf( stderr, "<INFO> starting wormhole tests\n" );
index 14c678f..1eae96d 100644 (file)
@@ -114,6 +114,7 @@ static int sr_nano_test() {
        ctx->max_plen = RMR_MAX_RCV_BYTES + sizeof( uta_mhdr_t );
        ctx->max_mlen = ctx->max_plen + sizeof( uta_mhdr_t );
        ctx->my_name = strdup( "dummy-test" );
+       ctx->my_ip = strdup( "30.4.19.86:1111" );
        uta_lookup_rtg( ctx );
 
        gen_rt( ctx );                                                          // forces a static load with some known info since we don't start the rtc()
index 809deba..294207c 100644 (file)
@@ -130,6 +130,7 @@ static int sr_nng_test() {
        ctx->max_plen = RMR_MAX_RCV_BYTES + sizeof( uta_mhdr_t );
        ctx->max_mlen = ctx->max_plen + sizeof( uta_mhdr_t );
        ctx->my_name = strdup( "dummy-test" );
+       ctx->my_ip = strdup( "30.4.19.86:1111" );
        uta_lookup_rtg( ctx );
 
        gen_rt( ctx );                                                          // forces a static load with some known info since we don't start the rtc()
index c2101f5..88f5966 100644 (file)
@@ -50,12 +50,37 @@ static int rcv_delay = 0;                   // forced delay before call to rcvmsg starts to work
 
 static int gates_ok = 0;
 static pthread_mutex_t rcv_gate;
+static int em_gen_long_hostname = 0;           // if set the emulated hostname generates a longer name (>40 char)
 
 
+// ----------- gethostname emulation ---------------------------------------
+#define gethostname  em_gethostname
+static int em_gethostname( char* buf, size_t len ) {
+       if( len < 1 ) {
+               errno = EINVAL;
+               return 1;
+       }
+
+       if( em_gen_long_hostname ) {
+               snprintf( buf, len, "hostname-which-is-long-a860430b890219-dfw82" );
+       } else {
+               snprintf( buf, len, "em-hostname" );
+       }
+
+       return 0;
+}
+
+static int em_set_long_hostname( int v ) {
+       em_gen_long_hostname = !!v;
+}
+
 // ----------- epoll emulation ---------------------------------------------
 
-// CAUTION: sys/epoll.h must be included before this define and function will properly compile.
+// CAUTION: sys/epoll.h must be included before these define and function will properly compile.
 #define epoll_wait em_wait
+#define epoll_ctl  em_ep_ctl
+#define epoll_create  em_ep_create
+
 /*
        Every other call returns 1 ready; alternate calls return 0 ready.
        Mostly for testing the timeout receive call. First call should return
@@ -69,6 +94,14 @@ static int em_wait( int fd, void* events, int n, int to ) {
        return ready;
 }
 
+int em_ep_ctl( int epfd, int op, int fd, struct epoll_event *event ) {
+       return 0;
+}
+
+int em_ep_create( int size ) {
+       return 0;
+}
+
 
 
 /*
@@ -92,7 +125,7 @@ struct em_msg {
        we don't add a payload even if setting a v1 type.
 */
 #define ALT_MSG_VER 1  // alternate every so often
-#define MSG_VER 2              // default version to insert
+#define MSG_VER 3              // default version to insert
 struct em_msg {
        int32_t mtype;                                          // message type  ("long" network integer)
        int32_t plen;                                           // payload length
@@ -110,6 +143,9 @@ struct em_msg {
        int32_t len2;                       // length of data 1 (d1)
        int32_t len3;                       // length of data 2 (d2)
        int32_t sub_id;                                         // subscription id (-1 invalid)
+
+                                                                               // V3 stuff
+       unsigned char srcip[64];                                // sender ID for return to sender needs
 };
 
 
@@ -195,8 +231,8 @@ static int em_nng_recvmsg( nng_socket s, nng_msg ** m, int i ) {
                d1_size = 4;
        }
 
-       b = (void *) malloc( 2048 );
        if( m != NULL ) {
+               b = (void *) malloc( 2048 );
                memset( b, 0, 2048 );
 
                *m = (nng_msg *) b;
@@ -231,10 +267,14 @@ static int em_nng_recvmsg( nng_socket s, nng_msg ** m, int i ) {
                }
                pthread_mutex_unlock( &rcv_gate );
                snprintf( msg->xid, 32, "%015d", rcv_count );           // simple transaction id so we can test receive specific and ring stuff
-               snprintf( msg->src, 16, "localhost:4562" );             // set src id (unrealistic) so that rts() can be tested
+               snprintf( msg->src, 64, "localhost:4562" );             // set src id (unrealistic) so that rts() can be tested
+               snprintf( msg->srcip, 64, "89.2.19.19:4562" );          // set src ip for rts testing
+
+               //fprintf( stderr, ">>> simulated received message: %s %s p=%p len0=%d\n", msg->src, msg->srcip, msg, (int) ntohl( msg->len0 ) );
+       } else {
+               fprintf( stderr, "<WARN> em: simulated receive no msg pointer provided\n" );
        }
 
-       //fprintf( stderr, ">>> simulated received message: %s\n", msg->xid );
        return return_value;
 }
 
@@ -452,6 +492,7 @@ static int em_nn_recv (int s, void *m, size_t len, int flags ) {
        static int count = 0;                   // we'll simulate a message going in by dropping an rmr-ish msg with transaction id only
        int trace_size = 0;
        static int counter = 0;                         // if timeout value is set; we return timeout (eagain) every 3 calls
+       int d1_size = 0;
 
        if( em_timeout > 0 ) {
                counter++;
@@ -460,6 +501,10 @@ static int em_nn_recv (int s, void *m, size_t len, int flags ) {
                }
        }
 
+       if( em_mtc_msgs ) {
+               d1_size = 4;
+       }
+
        b = (void *) malloc( 2048 );
        if( m != NULL ) {                                               // blindly we assume this is 2k or bigger
                memset( m, 0, 2048 );
@@ -474,14 +519,17 @@ static int em_nn_recv (int s, void *m, size_t len, int flags ) {
                msg->plen = htonl( 220 );
                msg->len0 = htonl( sizeof( struct em_msg ) );
                msg->len1 = htonl( trace_size );
+               msg->len2 = htonl( d1_size );
+               msg->len3 = htonl( 0 );
                snprintf( msg->xid, 32, "%015d", count++ );             // simple transaction id so we can test receive specific and ring stuff
-               snprintf( msg->src, 16, "localhost:4562" );             // set src id (unrealistic) so that rts() can be tested
+               snprintf( msg->src, 64, "localhost:4562" );             // set src id (unrealistic) so that rts() can be tested
+               snprintf( msg->srcip, 64, "89.2.19.19:4562" );          // set src ip for rts testing
                //fprintf( stderr, "<EM>   returning message len=%d\n\n", ntohl( msg->plen ) );
        } else {
                fprintf( stderr, "<EM>   message was nil\n\n" );
        }
 
-       //fprintf( stderr, ">>> simulated received message: %s len=%d\n", msg->xid, msg->plen );
+       //fprintf( stderr, ">>> simulated received message: %s %s len=%d p=%p\n", msg->src, msg->srcip, ntohl( msg->plen ), m );
        return 2048;
 }
 
index f036590..08254a0 100644 (file)
@@ -138,11 +138,29 @@ static int fail_if_equal( int a, int b, char* what ) {
        return a != b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
 }
 
+static int fail_not_equalp( void* a, void* b, char* what ) {
+       if( a != b ) {
+               fprintf( stderr, "<FAIL> %s: pointers were not equal a=%p b=%p\n", what, a, b );
+       }
+       return a == b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
+}
+
+static int fail_if_equalp( void* a, void* b, char* what ) {
+       if( a == b ) {
+               fprintf( stderr, "<FAIL> %s pointers were equal a=%p b=%p\n", what, a, b );
+       }
+       return a != b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
+}
+
 
 #ifndef NO_DUMMY_RMR
 /*
        Dummy message allocator for testing without sr_static functions
 */
+#ifndef MSG_VER
+#define MSG_VER 3
+#endif
+
 static rmr_mbuf_t* test_mk_msg( int len, int tr_len ) {
        rmr_mbuf_t*     new_msg;
        uta_mhdr_t* hdr;
@@ -157,6 +175,9 @@ static rmr_mbuf_t* test_mk_msg( int len, int tr_len ) {
        hdr = (uta_mhdr_t*) new_msg->tp_buf;
        SET_HDR_LEN( hdr );
        SET_HDR_TR_LEN( hdr, tr_len );
+       hdr->rmr_ver = htonl( MSG_VER );
+       strcpy( hdr->src, "dummyhost:1111" );
+       strcpy( hdr->srcip, "30.4.19.86:1111" );
 
        new_msg->header = new_msg->tp_buf;
        new_msg->payload =  new_msg->header + PAYLOAD_OFFSET( hdr );
@@ -165,6 +186,18 @@ static rmr_mbuf_t* test_mk_msg( int len, int tr_len ) {
 
        return new_msg;
 }
+
+static void test_set_ver( rmr_mbuf_t* msg, int ver ) {
+       uta_mhdr_t* hdr;
+
+       hdr = (uta_mhdr_t*) msg->tp_buf;
+       hdr->rmr_ver = htonl( ver );
+       strcpy( hdr->src, "dummyhost-v2:1111" );
+       strcpy( hdr->srcip, "30.4.19.86:2222" );
+
+       return;
+}
 #endif
 
+
 #endif
index b8ea612..9e156ec 100644 (file)
        Date:           3 April 2019
 */
 
+/*
+       Returns an interface name that is valid in this environment (keeps us from
+       having to know/guess a name to test with.
+*/
+static char* get_ifname( ) {
+       if_addrs_t* l;
+       struct  ifaddrs *ifs;           // pointer to head
+       struct  ifaddrs *ele;           // pointer into the list
+       char*   rstr = NULL;            // return string
+
+
+       if( (l = (if_addrs_t *) malloc( sizeof( if_addrs_t ) )) == NULL ) {
+               return NULL;
+       }
+       memset( l, 0, sizeof( if_addrs_t ) );
+       l->addrs = (char **) malloc( sizeof( char* ) * 128 );
+       if( l->addrs == NULL ) {
+               free( l );
+               return NULL;
+       }
+
+       getifaddrs( &ifs );
+       for( ele = ifs; ele; ele = ele->ifa_next ) {
+               if( ele && strcmp( ele->ifa_name, "lo" ) ) {
+                       rstr = strdup( ele->ifa_name );
+                       break;
+               }
+       }
+
+       free( l );
+       return rstr;
+}
 
 static int tools_test( ) {
        int i;
@@ -40,6 +72,7 @@ static int tools_test( ) {
        char* buf = "2,Fred,Wilma,Barney,Betty,Dino,Pebbles,Bambam,Mr. Slate,Gazoo";
        char*   dbuf;                           // duplicated buf since C marks a const string is unumtable
        char*   hname;
+       char*   ip;                                     // ip address string
        uta_ctx_t ctx;                          // context for uta_lookup test
        void*   if_list;
 
@@ -150,5 +183,29 @@ static int tools_test( ) {
        i = has_myip( "192.168.4.30:1235", if_list, ',', 128 );                                                                                 // should find our ip when only in list
        errors += fail_if_false( i, "has_myip did not find IP when only one in list" );
 
+       ip = get_default_ip( NULL );
+       errors += fail_not_nil( ip, "get_default_ip returned non-nil pointer when given nil information" );
+
+       ip = get_default_ip( if_list );
+       if( ip ) {
+       } else {
+               errors += fail_if_nil( ip, "get_defaul_ip returned nil pointer when valid pointer expected" );
+       }
+
+       ip = get_ifname();                                                      // suss out a valid interface name (not lo)
+       if( ip ) {
+               setenv( "RMR_BIND_IF", ip, 1 );                 // drive the case where we have a hard set interface; and set known interface in list
+               free( ip );
+               if_list = mk_ip_list( "1235" );
+               if( if_list ) {
+                       ip = get_default_ip( if_list );
+                       errors += fail_if_nil( ip, "get_default_ip did not return valid pointer when list created from interface name" );
+               } else {
+                       errors += fail_if_nil( if_list, "mk_ip_list with a specific interface name returned a nil list" );
+               }
+       }
+
+// -------------------------------------------------------------------------------------------------
+
        return !!errors;                        // 1 or 0 regardless of count
 }
index 6725e9b..4bcd597 100644 (file)
@@ -70,112 +70,10 @@ struct uta_ctx {
 
 #include "tools_static.c"
 
+#include "tools_static_test.c"
 
 int main( ) {
-       int i;
-       int j;
-       int errors = 0;
-       char* tokens[127];
-       char* buf = "2,Fred,Wilma,Barney,Betty,Dino,Pebbles,Bambam,Mr. Slate,Gazoo";
-       char*   dbuf;                           // duplicated buf since C marks a const string is unumtable
-       char*   hname;
-       uta_ctx_t ctx;                          // context for uta_lookup test
-       void*   if_list;
-
-
-       // ------------------ tokenise tests -----------------------------------------------------------
-       dbuf = strdup( buf );
-       i = uta_tokenise( dbuf, tokens, 127, ',' );
-       errors += fail_not_equal( i, 10, "unexpected number of tokens returned (comma sep)" );
-       for( j = 0; j < i; j++ ) {
-               //fprintf( stderr, ">>>> [%d] (%s)\n", j, tokens[j] );
-               errors += fail_if_nil( tokens[j], "token from buffer" );
-       }
-       errors += fail_not_equal( strcmp( tokens[4], "Betty" ), 0, "4th token wasn't 'Betty'" );
-
-       free( dbuf );
-       dbuf = strdup( buf );
-       i = uta_tokenise( dbuf, tokens, 127, '|' );
-       errors += fail_not_equal( i, 1, "unexpected number of tokens returned (bar sep)" );
-       free( dbuf );
-
-       // ------------ has str tests -----------------------------------------------------------------
-       j = uta_has_str( buf, "Mr. Slate", ',', 1 );                    // should fail (-1) because user should use strcmp in this situation
-       errors += fail_if_true( j >= 0, "test to ensure has str rejects small max" );
-
-       j = uta_has_str( buf, "Mr. Slate", ',', 27 );
-       errors += fail_if_true( j < 0, "has string did not find Mr. Slate" );
-
-       j = uta_has_str( buf, "Mrs. Slate", ',', 27 );
-       errors += fail_if_true( j >= 0, "has string not found Mrs. Slate" );
-
-       // ------------ host name 2 ip tests ---------------------------------------------------------
-       hname = uta_h2ip( "192.168.1.2" );
-       errors += fail_not_equal( strcmp( hname, "192.168.1.2" ), 0, "h2ip did not return IP address when given address" );
-       errors += fail_if_nil( hname, "h2ip did not return a pointer" );
-
-       hname = uta_h2ip( "yahoo.com" );
-       errors += fail_if_nil( hname, "h2ip did not return a pointer" );
-
-       hname = uta_h2ip( "yahoo.com:1234" );                                                   // should ignore the port
-       errors += fail_if_nil( hname, "h2ip did not return a pointer" );
-
-       // ------------ rtg lookup test -------------------------------------------------------------
-       ctx.rtg_port = 0;
-       ctx.rtg_addr = NULL;
-
-       i = uta_lookup_rtg( NULL );                                             // ensure it handles a nil context
-       errors += fail_if_true( i, "rtg lookup returned that it found something when not expected to (nil context)" );
-
-       setenv( "RMR_RTG_SVC", "localhost:1234", 1);
-       i = uta_lookup_rtg( &ctx );
-       errors += fail_if_false( i, "rtg lookup returned that it did not find something when expected to" );
-       errors += fail_if_nil( ctx.rtg_addr, "rtg lookup did not return a pointer (with port)" );
-       errors += fail_not_equal( ctx.rtg_port, 1234, "rtg lookup did not capture the port" );
-
-       setenv( "RMR_RTG_SVC", "localhost", 1);                 // test ability to generate default port
-       uta_lookup_rtg( &ctx );
-       errors += fail_if_nil( ctx.rtg_addr, "rtg lookup did not return a pointer (no port)" );
-       errors += fail_not_equal( ctx.rtg_port, 5656, "rtg lookup did not return default port" );
-
-       unsetenv( "RMR_RTG_SVC" );                                              // this should fail as the default name (rtg) will be unknown during testing
-       i = uta_lookup_rtg( &ctx );
-       errors += fail_if_true( i, "rtg lookup returned that it found something when not expected to" );
-
-
-       // ------------ my ip stuff -----------------------------------------------------------------
-
-       if_list = mk_ip_list( "1235" );
-       errors += fail_if_nil( if_list, "mk_ip_list returned nil pointer" );
-
-       i = has_myip( NULL, NULL, ',', 128 );           // should be false if pointers are nil
-       errors += fail_if_true( i, "has_myip returned true when given nil buffer" );
-
-       i = has_myip( "buffer contents not valid", NULL, ',', 128 );            // should be false if pointers are nil
-       errors += fail_if_true( i, "has_myip returned true when given nil list" );
-
-       i = has_myip( "buffer contents not valid", NULL, ',', 1 );                      // should be false if max < 2
-       errors += fail_if_true( i, "has_myip returned true when given small max value" );
-
-       i = has_myip( "buffer.contents.not.valid", if_list, ',', 128 );         // should be false as there is nothing valid in the list
-       errors += fail_if_true( i, "has_myip returned true when given a buffer with no valid info" );
-
-
-       setenv( "RMR_BIND_IF", "192.168.4.30", 1 );                     // drive the case where we have a hard set interface; and set known interface in list
-       if_list = mk_ip_list( "1235" );
-       errors += fail_if_nil( if_list, "mk_ip_list with env set returned nil pointer" );
-
-       i = has_myip( "192.168.1.2:1235,192.168.4.30:1235,192.168.2.19:4567", if_list, ',', 128 );              // should find our ip in middle
-       errors += fail_if_false( i, "has_myip did not find IP in middle of list" );
-
-       i = has_myip( "192.168.4.30:1235,192.168.2.19:4567,192.168.2.19:2222", if_list, ',', 128 );             // should find our ip at head
-       errors += fail_if_false( i, "has_myip did not find IP at head of list" );
-
-       i = has_myip( "192.168.23.45:4444,192.168.1.2:1235,192.168.4.30:1235", if_list, ',', 128 );             // should find our ip at end
-       errors += fail_if_false( i, "has_myip did not find IP at tail of list" );
-
-       i = has_myip( "192.168.4.30:1235", if_list, ',', 128 );                                                                                 // should find our ip when only in list
-       errors += fail_if_false( i, "has_myip did not find IP when only one in list" );
-
-       return errors > 0;                      // overall exit code bad if errors
+       fprintf( stderr, ">>>> starting tools_test\n" );
+       return tools_test() > 0;
 }
+
index 06cb36c..47bd85f 100644 (file)
@@ -63,6 +63,7 @@ static int worm_test( ) {
        }
        memset( ctx, 0, sizeof( *ctx ) );
        ctx->my_name = strdup( "tester" );
+       ctx->my_ip = strdup( "30.4.19.86:1111" );
 
        gen_rt( ctx );