Eliminate the SI receive buffer length requirement
[ric-plt/lib/rmr.git] / src / rmr / si / src / sr_si_static.c
index 40ae61b..3919621 100644 (file)
@@ -41,9 +41,9 @@ static void dump_n( char *p, char* label, int n ) {
        if( label ) {
                fprintf( stderr, ">>>>> %s p=%p %d bytes\n", label, p, n );
        }
-       
+
        rows = (n/16) + ((n % 16) ? 1 : 0);
-       
+
        for( j = 0; j < rows; j++ ) {
                fprintf( stderr, "%04x: ", j * 16 );
 
@@ -59,7 +59,7 @@ static void dump_n( char *p, char* label, int n ) {
        backwards compatability.
 */
 static void dump_40( char *p, char* label ) {
-       dump_n( p, label, 40 ); 
+       dump_n( p, label, 40 );
 }
 
 /*
@@ -70,7 +70,7 @@ static void dump_40( char *p, char* label ) {
 
        The addition of the connection shut error code to the switch requires
        that the NNG version at commit e618abf8f3db2a94269a (or after) be
-       used for compiling RMR. 
+       used for compiling RMR.
 */
 static inline int xlate_si_state( int state, int def_state ) {
 
@@ -110,6 +110,25 @@ static inline int xlate_si_state( int state, int def_state ) {
        return state;
 }
 
+/*
+       Given a message size and a buffer (assumed to be TP_SZFIELD_LEN or larger)
+       this will put in the size such that it is compatable with old versions
+       of RMR (that expect the message size to not be in network byte order)
+       and with new versions that do. See extract function in mt_call_si_static.c
+       for details on what ends up in the buffer.
+*/
+static inline void insert_mlen( uint32_t len, char* buf ) {
+       uint32_t* blen;                                                 // pointer into buffer where we'll add the len
+
+       blen = (uint32_t *) buf;                                // old systems expect an unconverted integer
+       *blen = len;
+
+       blen++;
+       *blen = htonl( len );                                   // new systems want a converted integer
+
+       buf[TP_SZFIELD_LEN-1] = TP_SZ_MARKER;   // marker to flag this is generated by a new message
+}
+
 /*
        Alloc a new nano zero copy buffer and put into msg. If msg is nil, then we will alloc
        a new message struct as well. Size is the size of the zc buffer to allocate (not
@@ -161,13 +180,13 @@ static rmr_mbuf_t* alloc_zcmsg( uta_ctx_t* ctx, rmr_mbuf_t* msg, int size, int s
                abort( );                                                                                       // toss out a core file for this
        }
 
-#ifdef DEBUG
-       memset( msg->tp_buf, 0, mlen );    // NOT for production (debug only)   valgrind will complain about uninitalised use if we don't set
-       memcpy( msg->tp_buf, "@@!!@@!!@@!!@@!!@@!!@@!!@@!!@@!!**", TP_HDR_LEN );                // NOT for production -- debugging eyecatcher
-#endif
+       if( DEBUG ) {
+               // for speed we don't do this in production; for testing valgrind will complain about uninitialised use if not set
+               memset( msg->tp_buf, 0, mlen );
+               memcpy( msg->tp_buf, "@@!!@@!!@@!!@@!!@@!!@@!!@@!!@@!!==", 34 );                // do NOT use a $ in this string!
+       }
 
-       alen = (int *) msg->tp_buf;
-       *alen = mlen;                                           // FIX ME: need a stuct to go in these first bytes, not just dummy len
+       insert_mlen( (uint32_t) mlen, msg->tp_buf );                    // this will likely be overwriten on send to shirnk
 
        msg->header = ((char *) msg->tp_buf) + TP_HDR_LEN;
        memset( msg->header, 0, sizeof( uta_mhdr_t ) );                         // ensure no junk in the header area
@@ -391,10 +410,12 @@ static inline rmr_mbuf_t* realloc_msg( rmr_mbuf_t* old_msg, int tr_len  ) {
                rmr_vlog( RMR_VL_CRIT, "rmr_clone: cannot get memory for zero copy buffer: %d\n", ENOMEM );
                exit( 1 );
        }
-       memset( nm->tp_buf, 0, tpb_len );
-       memcpy( nm->tp_buf, "@@!!@@!!@@!!@@!!@@!!@@!!@@!!@@!!**", 34 );         // DEBUGGING
-       alen = (int *) nm->tp_buf;
-       *alen = tpb_len;                                                // FIX ME: need a stuct to go in these first bytes, not just dummy len
+       if( DEBUG ) {
+               memset( nm->tp_buf, 0, tpb_len );
+               memcpy( nm->tp_buf, "@@!!@@!!@@!!@@!!@@!!@@!!@@!!@@!!==", 34 );         // DEBUGGING do NOT use $ in this string!!
+       }
+
+       insert_mlen( (uint32_t) tpb_len, nm->tp_buf );                  // this len will likely be reset on send to shrink
 
        nm->header = ((char *) nm->tp_buf) + TP_HDR_LEN;
 
@@ -436,7 +457,7 @@ static inline rmr_mbuf_t* realloc_msg( rmr_mbuf_t* old_msg, int tr_len  ) {
 }
 
 /*
-       Realloc the message such that the payload is at least payload_len bytes.  
+       Realloc the message such that the payload is at least payload_len bytes.
        The clone and copy options affect what portion of the original payload is copied to
        the reallocated message, and whether or not the original payload is lost after the
        reallocation process has finished.
@@ -459,7 +480,7 @@ static inline rmr_mbuf_t* realloc_msg( rmr_mbuf_t* old_msg, int tr_len  ) {
                clone == false
                The old payload will be lost after reallocation. The message buffer pointer which
                is returned will likely reference the same structure (don't depend on that).
-               
+
 
        CAUTION:
        If the message is not a message which was received, the mtype, sub-id, length values in the
@@ -520,7 +541,7 @@ static inline rmr_mbuf_t* realloc_payload( rmr_mbuf_t* old_msg, int payload_len,
        omhdr = old_msg->header;
        mlen = hdr_len + (payload_len > old_psize ? payload_len : old_psize);           // must have larger in case copy is true
 
-       if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "reallocate for payload increase. new message size: %d\n", (int) mlen );    
+       if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "reallocate for payload increase. new message size: %d\n", (int) mlen );
        if( (nm->tp_buf = (char *) malloc( sizeof( char ) * mlen )) == NULL ) {
                rmr_vlog( RMR_VL_CRIT, "rmr_realloc_payload: cannot get memory for zero copy buffer. bytes requested: %d\n", (int) mlen );
                free( nm );
@@ -580,7 +601,7 @@ exit( 1 );
        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 
+       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, int nn_sock, int retries ) {
@@ -615,7 +636,7 @@ static rmr_mbuf_t* send_msg( uta_ctx_t* ctx, rmr_mbuf_t* msg, int nn_sock, int r
                if( tot_len > msg->alloc_len ) {
                        tot_len = msg->alloc_len;                                                                       // likely bad length from user :(
                }
-               *((int*) msg->tp_buf) = tot_len;
+               insert_mlen( tot_len, msg->tp_buf );    // shrink to fit
 
                if( DEBUG > 1 ) rmr_vlog( RMR_VL_DEBUG, "send_msg: ending %d (%x) bytes  usr_len=%d alloc=%d retries=%d\n", tot_len, tot_len, msg->len, msg->alloc_len, retries );
                if( DEBUG > 2 ) dump_40( msg->tp_buf, "sending" );
@@ -679,8 +700,8 @@ static rmr_mbuf_t* send_msg( uta_ctx_t* ctx, rmr_mbuf_t* msg, int nn_sock, int r
        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 
+       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
@@ -761,7 +782,7 @@ static  rmr_mbuf_t* mtosend_msg( void* vctx, rmr_mbuf_t* msg, int max_to ) {
                                if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "msg cloned: type=%d len=%d\n", msg->mtype, msg->len );
                                msg->flags |= MFL_NOALLOC;                                                              // keep send from allocating a new message; we have a clone to use
                                msg = send_msg( ctx, msg, nn_sock, max_to );                    // do the hard work, msg should be nil on success
-       
+
                                if( msg != NULL ) {                                                                             // returned message indicates send error of some sort
                                        rmr_free_msg( msg );                                                            // must ditchone; pick msg so we don't have to unfiddle flags
                                        msg = clone_m;
@@ -773,7 +794,7 @@ static  rmr_mbuf_t* mtosend_msg( void* vctx, rmr_mbuf_t* msg, int max_to ) {
                                msg = send_msg( ctx, msg, nn_sock, max_to );                    // send the last, and allocate a new buffer; drops the clone if it was
                                if( DEBUG ) {
                                        if( msg == NULL ) {
-                                               rmr_vlog( RMR_VL_DEBUG, "mtosend_msg:  send returned nil message!\n" );         
+                                               rmr_vlog( RMR_VL_DEBUG, "mtosend_msg:  send returned nil message!\n" );
                                        }
                                }
                        }
@@ -783,7 +804,7 @@ static  rmr_mbuf_t* mtosend_msg( void* vctx, rmr_mbuf_t* msg, int max_to ) {
                                        case RMR_OK:
                                                ep->scounts[EPSC_GOOD]++;
                                                break;
-                               
+       
                                        case RMR_ERR_RETRY:
                                                ep->scounts[EPSC_TRANS]++;
                                                break;
@@ -806,9 +827,9 @@ static  rmr_mbuf_t* mtosend_msg( void* vctx, rmr_mbuf_t* msg, int max_to ) {
                if( ok_sends ) {                                // multiple rr-groups and one was successful; report ok
                        msg->state = RMR_OK;
                }
-       
+
                if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "final send stats: ok=%d group=%d state=%d\n", ok_sends, group, msg->state );
-       
+
                msg->tp_state = errno;
        }