Allow endpoint selection based on meid in message
[ric-plt/lib/rmr.git] / src / rmr / common / src / mbuf_api.c
index e801ac9..c879d7c 100644 (file)
@@ -22,7 +22,9 @@
        Mnemonic:       mbuf_api.c
        Abstract:       These are common functions which work only on the mbuf and
                                thus (because they do not touch an endpoint or context)
-                               can be agnostic to the underlying transport.
+                               can be agnostic to the underlying transport, or the transport
+                               layer provides a transport specific function (e.g. payload 
+                               reallocation).
 
        Author:         E. Scott Daniels
        Date:           8 February 2019
@@ -34,6 +36,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <semaphore.h>
 
 #include "rmr.h"                               // things the users see
 #include "rmr_agnostic.h"              // agnostic things (must be included before private)
                EINVAL id poitner, buf or buf header are bad.
                EOVERFLOW if the bytes given would have overrun
 
+       We have been told that the meid will be a string, so we enforce that even if
+       the user is copying in bytes.  We will add a 0 byte at len+1 when len is less
+       than the field size, or as the last byte (doing damage to their string) if
+       the caller didn't play by the rules. If they pass a non-nil terminated set
+       of bytes which are the field length, we'll indicate truncation.
+
 */
 extern int rmr_bytes2meid( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
        uta_mhdr_t* hdr;
@@ -63,11 +72,20 @@ extern int rmr_bytes2meid( rmr_mbuf_t* mbuf, unsigned char const* src, int len )
        if( len > RMR_MAX_MEID ) {
                len = RMR_MAX_MEID;
                errno = EOVERFLOW;
-       }
+       } 
 
        hdr = (uta_mhdr_t *) mbuf->header;
        memcpy( hdr->meid, src, len );
 
+       if( len == RMR_MAX_MEID ) {
+               if( *(hdr->meid+len-1) != 0 ) {
+                       *(hdr->meid+len-1) = 0;
+                       errno = EOVERFLOW;
+               }
+       } else {
+               *(hdr->meid+len) = 0;
+       }
+
        return len;
 }
 
@@ -187,6 +205,39 @@ extern int rmr_str2xact( rmr_mbuf_t* mbuf, unsigned char const* str ) {
        return RMR_OK;
 }
 
+/*
+       Extracts the transaction bytes from the header and places into a
+       user supplied buffer (dest). The buffer must be at least RMR_MAX_XID
+       bytes in length as this function will copy the entire field (even if
+       the sender saved a shorter "string." If the user supplies a nil poniter
+       as the destination, a buffer is allocated; the caller must free when
+       finished.  The buffer will be exactly RMR_MAX_XID bytes long.
+
+       The return value is a pointer to the buffer that was filled (to
+       the dest buffer provided, or the buffer we allocated). If there is an
+       error, a nil pointer is returned, and errno should suggest the root
+       cause of the issue (invalid message or no memory).
+*/
+extern unsigned char*  rmr_get_xact( rmr_mbuf_t* mbuf, unsigned char* dest ) {
+       errno = 0;
+
+       if( mbuf == NULL || mbuf->xaction == NULL ) {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       if( ! dest ) {
+               if( (dest = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_XID )) == NULL ) {
+                       errno = ENOMEM;
+                       return NULL;
+               }
+       }
+
+       memcpy( dest, mbuf->xaction, RMR_MAX_XID );
+
+       return dest;
+}
+
 /*
        Extracts the meid (managed equipment) from the header and copies the bytes
        to the user supplied area. If the user supplied pointer is nil, then
@@ -199,6 +250,8 @@ extern int rmr_str2xact( rmr_mbuf_t* mbuf, unsigned char const* str ) {
 extern unsigned char*  rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest ) {
        uta_mhdr_t* hdr;
 
+       errno = 0;
+
        if( mbuf == NULL || mbuf->header == NULL ) {
                errno = EINVAL;
                return NULL;
@@ -212,7 +265,7 @@ extern unsigned char*  rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest ) {
        }
 
        hdr = (uta_mhdr_t *) mbuf->header;
-       memcpy( dest, hdr->meid, RMR_MAX_XID );
+       memcpy( dest, hdr->meid, RMR_MAX_MEID );
 
        return dest;
 }
@@ -246,6 +299,11 @@ extern int rmr_set_trace( rmr_mbuf_t* msg, unsigned const char* data, int size )
        }
 
        hdr = (uta_mhdr_t *) msg->header;
+       if( !hdr ) {
+               errno = EINVAL;
+               return 0;
+       }
+
        len = RMR_TR_LEN( hdr );
 
        if( len != size ) {                                                     // different sized trace data, must realloc the buffer
@@ -273,6 +331,41 @@ extern int rmr_set_trace( rmr_mbuf_t* msg, unsigned const char* data, int size )
 }
 
 
+/*
+       Returns a pointer (reference) to the trace data in the message. If sizeptr
+       is supplied, then the trace data size is assigned to the referenced
+       integer so that the caller doesn't need to make a second call to get the
+       value.
+
+       CAUTION:  user programmes should avoid writing to the referenced trace
+                       area (use rmr_set_trace() to avoid possible data overruns. This
+                       function is a convenience, and it is expected that users will
+                       use the trace data as read-only so as a copy is not necessary.
+*/
+extern void* rmr_trace_ref( rmr_mbuf_t* msg, int* sizeptr ) {
+       uta_mhdr_t*     hdr = NULL;
+       int size = 0;
+
+       if( sizeptr != NULL ) {
+               *sizeptr = 0;                                   // ensure reset if we bail
+       }
+
+       if( msg == NULL ) {
+               return NULL;
+       }
+
+       hdr = msg->header;
+       if( (size = RMR_TR_LEN( hdr )) <= 0 ) {
+               return NULL;
+       }
+
+       if( sizeptr != NULL ) {
+               *sizeptr = size;
+       }
+
+       return (void *) TRACE_ADDR( hdr );
+}
+
 /*
        Copies the trace bytes from the message header into the buffer provided by
        the user. If the trace data in the header is less than size, then only
@@ -341,3 +434,34 @@ 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;
+}
+