1 // : vi ts=4 sw=4 noet :
3 ==================================================================================
4 Copyright (c) 2019 Nokia
5 Copyright (c) 2018-2019 AT&T Intellectual Property.
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 ==================================================================================
23 Abstract: These are common functions which work only on the mbuf and
24 thus (because they do not touch an endpoint or context)
25 can be agnostic to the underlying transport, or the transport
26 layer provides a transport specific function (e.g. payload
29 Author: E. Scott Daniels
34 #include <netdb.h> // uint* types
39 #include <semaphore.h>
41 #include "rmr.h" // things the users see
42 #include "rmr_agnostic.h" // agnostic things (must be included before private)
45 // ---------- some wrappers need explicit copy-in functions, also header field setters -----
48 Allow the user programme to set the meid in the header. The meid is a fixed
49 length buffer in the header and thus we must ensure it is not overrun. If
50 the user gives a source buffer that is too large, we truncate. The return
51 value is the number of bytes copied, or -1 for absolute failure (bad pointer
53 EINVAL id poitner, buf or buf header are bad.
54 EOVERFLOW if the bytes given would have overrun
56 We have been told that the meid will be a string, so we enforce that even if
57 the user is copying in bytes. We will add a 0 byte at len+1 when len is less
58 than the field size, or as the last byte (doing damage to their string) if
59 the caller didn't play by the rules. If they pass a non-nil terminated set
60 of bytes which are the field length, we'll indicate truncation.
63 extern int rmr_bytes2meid( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
66 if( src == NULL || mbuf == NULL || mbuf->header == NULL ) {
72 if( len > RMR_MAX_MEID ) {
77 hdr = (uta_mhdr_t *) mbuf->header;
78 memcpy( hdr->meid, src, len );
80 if( len == RMR_MAX_MEID ) {
81 if( *(hdr->meid+len-1) != 0 ) {
82 *(hdr->meid+len-1) = 0;
93 Allows the user programme to set the meid from a string. The end of string
94 (nil) will be included UNLESS the total length including the end of string
95 would exceed the size of the space in the header for the meid. The return
96 value is RMR_OK for success and !RMR_OK on failure. Errno will be set
99 extern int rmr_str2meid( rmr_mbuf_t* mbuf, unsigned char const* str ) {
100 int len; // len moved -- we do validate
102 if( str == NULL || mbuf == NULL || mbuf->header == NULL ) {
104 return RMR_ERR_BADARG;
108 if( (len = strlen( (char *) str )) > RMR_MAX_MEID-1 ) {
110 return RMR_ERR_OVERFLOW;
113 rmr_bytes2meid( mbuf, str, len+1 );
120 This will copy n bytes from source into the payload. If len is larger than
121 the payload only the bytes which will fit are copied, The user should
122 check errno on return to determine success or failure.
124 extern void rmr_bytes2payload( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
125 if( src == NULL || mbuf == NULL || mbuf->payload == NULL ) {
131 mbuf->state = RMR_OK;
132 if( len > mbuf->alloc_len - sizeof( uta_mhdr_t ) ) {
133 mbuf->state = RMR_ERR_OVERFLOW;
135 len = mbuf->alloc_len - sizeof( uta_mhdr_t );
139 memcpy( mbuf->payload, src, len );
143 This will copy a nil terminated string to the mbuf payload. The buffer length
144 is set to the string length.
146 extern void rmr_str2payload( rmr_mbuf_t* mbuf, unsigned char const* str ) {
147 rmr_bytes2payload( mbuf, str, strlen( (char *) str ) + 1 );
152 Allow the user programme to set the xaction field in the header. The xaction
153 is a fixed length buffer in the header and thus we must ensure it is not overrun.
154 If the user gives a source buffer that is too large, we truncate. The return
155 value is the number of bytes copied, or -1 for absolute failure (bad pointer
157 EINVAL id poitner, buf or buf header are bad.
158 EOVERFLOW if the bytes given would have overrun
161 extern int rmr_bytes2xact( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
164 if( src == NULL || mbuf == NULL || mbuf->header == NULL ) {
170 if( len > RMR_MAX_XID ) {
175 hdr = (uta_mhdr_t *) mbuf->header;
176 memcpy( hdr->xid, src, len );
184 Allows the user programme to set the xaction (xid) field from a string. The end
185 of string (nil) will be included UNLESS the total length including the end of string
186 would exceed the size of the space in the header for the xaction. The return
187 value is RMR_OK for success and !RMR_OK on failure. Errno will be set
190 extern int rmr_str2xact( rmr_mbuf_t* mbuf, unsigned char const* str ) {
191 int len; // len moved -- we do validate
193 if( str == NULL || mbuf == NULL || mbuf->header == NULL ) {
195 return RMR_ERR_BADARG;
199 if( (len = strlen( (char *) str )) > RMR_MAX_XID-1 ) {
201 return RMR_ERR_OVERFLOW;
204 rmr_bytes2xact( mbuf, str, len+1 );
209 Extracts the transaction bytes from the header and places into a
210 user supplied buffer (dest). The buffer must be at least RMR_MAX_XID
211 bytes in length as this function will copy the entire field (even if
212 the sender saved a shorter "string." If the user supplies a nil poniter
213 as the destination, a buffer is allocated; the caller must free when
214 finished. The buffer will be exactly RMR_MAX_XID bytes long.
216 The return value is a pointer to the buffer that was filled (to
217 the dest buffer provided, or the buffer we allocated). If there is an
218 error, a nil pointer is returned, and errno should suggest the root
219 cause of the issue (invalid message or no memory).
221 extern unsigned char* rmr_get_xact( rmr_mbuf_t* mbuf, unsigned char* dest ) {
224 if( mbuf == NULL || mbuf->xaction == NULL ) {
230 if( (dest = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_XID )) == NULL ) {
236 memcpy( dest, mbuf->xaction, RMR_MAX_XID );
242 Extracts the meid (managed entity) from the header and copies the bytes
243 to the user supplied area. If the user supplied pointer is nil, then
244 a buffer will be allocated and it is the user's responsibilty to free.
245 A pointer is returned to the destination memory (allocated or not)
246 for consistency. If the user programme supplies a destination it is
247 the responsibility of the programme to ensure that the space is large
250 extern unsigned char* rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest ) {
255 if( mbuf == NULL || mbuf->header == NULL ) {
261 if( (dest = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID )) == NULL ) {
267 hdr = (uta_mhdr_t *) mbuf->header;
268 memcpy( dest, hdr->meid, RMR_MAX_MEID );
273 // ------------------- trace related access functions --------------------------------------
275 The set_trace function will copy the supplied data for size bytes into the
276 header. If the header trace area is not large enough, a new one will be allocated
277 which will cause a payload copy based on the msg->len value (if 0 no payload
280 The return value is the number of bytes actually coppied. If 0 bytes are coppied
281 errno should indicate the reason. If 0 is returned and errno is 0, then size
282 passed was 0. The state in the message is left UNCHANGED.
284 extern int rmr_set_trace( rmr_mbuf_t* msg, unsigned const char* data, int size ) {
286 rmr_mbuf_t* nm; // new message if larger is needed
288 void* old_tp_buf; // if we need to realloc, must hold old to free
301 hdr = (uta_mhdr_t *) msg->header;
307 len = RMR_TR_LEN( hdr );
309 if( len != size ) { // different sized trace data, must realloc the buffer
310 nm = rmr_realloc_msg( msg, size ); // realloc with changed trace size
311 old_tp_buf = msg->tp_buf;
312 old_hdr = msg->header;
314 msg->tp_buf = nm->tp_buf; // reference the reallocated buffer
315 msg->header = nm->header;
316 msg->id = NULL; // currently unused
317 msg->xaction = nm->xaction;
318 msg->payload = nm->payload;
320 nm->tp_buf = old_tp_buf; // set to free
321 nm->header = old_hdr; // nano frees on hdr, so must set both
324 hdr = (uta_mhdr_t *) msg->header; // header WILL be different
325 len = RMR_TR_LEN( hdr );
328 memcpy( TRACE_ADDR( hdr ), data, size );
335 Returns a pointer (reference) to the trace data in the message. If sizeptr
336 is supplied, then the trace data size is assigned to the referenced
337 integer so that the caller doesn't need to make a second call to get the
340 CAUTION: user programmes should avoid writing to the referenced trace
341 area (use rmr_set_trace() to avoid possible data overruns. This
342 function is a convenience, and it is expected that users will
343 use the trace data as read-only so as a copy is not necessary.
345 extern void* rmr_trace_ref( rmr_mbuf_t* msg, int* sizeptr ) {
346 uta_mhdr_t* hdr = NULL;
349 if( sizeptr != NULL ) {
350 *sizeptr = 0; // ensure reset if we bail
358 if( (size = RMR_TR_LEN( hdr )) <= 0 ) {
362 if( sizeptr != NULL ) {
366 return (void *) TRACE_ADDR( hdr );
370 Copies the trace bytes from the message header into the buffer provided by
371 the user. If the trace data in the header is less than size, then only
372 that number of bytes are copied, else exactly size bytes are copied. The
373 number actually copied is returned.
375 extern int rmr_get_trace( rmr_mbuf_t* msg, unsigned char* dest, int size ) {
376 uta_mhdr_t* hdr = NULL;
383 if( size <= 0 || dest == NULL ) {
388 if( (n2copy = size < RMR_TR_LEN( hdr ) ? size : RMR_TR_LEN( hdr )) <= 0 ) {
392 memcpy( dest, TRACE_ADDR( hdr ), n2copy );
398 Returns the number of bytes currently allocated for trace data in the message
401 extern int rmr_get_trlen( rmr_mbuf_t* msg ) {
410 return RMR_TR_LEN( hdr );
414 Returns the string in the source portion of the header. This is assumed to be
415 something that can be used for direct sends (hostname:port). Regardless, it
416 will be a nil terminated, ascii string with max of 64 characters including
417 the final nil. So, the user must ensure that dest is at least 64 bytes.
419 As a convenience, the pointer to dest is returned on success; nil on failure
422 extern unsigned char* rmr_get_src( rmr_mbuf_t* msg, unsigned char* dest ) {
423 uta_mhdr_t* hdr = NULL;
432 strcpy( dest, hdr->src );
439 Returns the string with the IP address as reported by the sender. This is
440 the IP address that the sender has sussed off of one of the interfaces
441 and cannot be guarenteed to be the acutal IP address which was used to
442 establish the connection. The caller must provide a buffer of at least
443 64 bytes; the string will be nil terminated. A pointer to the user's buffer
444 is returned on success, nil on failure.
446 extern unsigned char* rmr_get_srcip( rmr_mbuf_t* msg, unsigned char* dest ) {
447 uta_mhdr_t* hdr = NULL;
452 if( dest != NULL && msg != NULL ) {
454 if( HDR_VERSION( msg->header ) > 2 ) { // src ip was not present in hdr until ver 3
456 strcpy( dest, hdr->srcip );
460 strcpy( dest, hdr->src ); // reutrn the name:port for old messages