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)
43 #include "rmr_logging.h"
45 //#define BUF_TOOLS_ONLY 1
46 #include "tools_static.c"
49 // ---------- some wrappers need explicit copy-in functions, also header field setters -----
52 Allow the user programme to set the meid in the header. The meid is a fixed
53 length buffer in the header and thus we must ensure it is not overrun. If
54 the user gives a source buffer that is too large, we truncate. The return
55 value is the number of bytes copied, or -1 for absolute failure (bad pointer
57 EINVAL id poitner, buf or buf header are bad.
58 EOVERFLOW if the bytes given would have overrun
60 We have been told that the meid will be a string, so we enforce that even if
61 the user is copying in bytes. We will add a 0 byte at len+1 when len is less
62 than the field size, or as the last byte (doing damage to their string) if
63 the caller didn't play by the rules. If they pass a non-nil terminated set
64 of bytes which are the field length, we'll indicate truncation.
67 extern int rmr_bytes2meid( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
70 if( src == NULL || mbuf == NULL || mbuf->header == NULL ) {
76 if( len > RMR_MAX_MEID ) {
81 hdr = (uta_mhdr_t *) mbuf->header;
82 memcpy( hdr->meid, src, len );
84 if( len == RMR_MAX_MEID ) {
85 if( *(hdr->meid+len-1) != 0 ) {
86 *(hdr->meid+len-1) = 0;
97 Allows the user programme to set the meid from a string. The end of string
98 (nil) will be included UNLESS the total length including the end of string
99 would exceed the size of the space in the header for the meid. The return
100 value is RMR_OK for success and !RMR_OK on failure. Errno will be set
103 extern int rmr_str2meid( rmr_mbuf_t* mbuf, unsigned char const* str ) {
104 int len; // len moved -- we do validate
106 if( str == NULL || mbuf == NULL || mbuf->header == NULL ) {
108 return RMR_ERR_BADARG;
112 if( (len = strlen( (char *) str )) > RMR_MAX_MEID-1 ) {
114 return RMR_ERR_OVERFLOW;
117 rmr_bytes2meid( mbuf, str, len+1 );
124 This will copy n bytes from source into the payload. If len is larger than
125 the payload only the bytes which will fit are copied, The user should
126 check errno on return to determine success or failure.
128 extern void rmr_bytes2payload( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
129 if( src == NULL || mbuf == NULL || mbuf->payload == NULL ) {
135 mbuf->state = RMR_OK;
136 if( len > mbuf->alloc_len - sizeof( uta_mhdr_t ) ) {
137 mbuf->state = RMR_ERR_OVERFLOW;
139 len = mbuf->alloc_len - sizeof( uta_mhdr_t );
143 memcpy( mbuf->payload, src, len );
147 This will copy a nil terminated string to the mbuf payload. The buffer length
148 is set to the string length.
150 extern void rmr_str2payload( rmr_mbuf_t* mbuf, unsigned char const* str ) {
151 rmr_bytes2payload( mbuf, str, strlen( (char *) str ) + 1 );
156 Allow the user programme to set the xaction field in the header. The xaction
157 is a fixed length buffer in the header and thus we must ensure it is not overrun.
158 If the user gives a source buffer that is too large, we truncate. The return
159 value is the number of bytes copied, or -1 for absolute failure (bad pointer
161 EINVAL id poitner, buf or buf header are bad.
162 EOVERFLOW if the bytes given would have overrun
165 extern int rmr_bytes2xact( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
168 if( src == NULL || mbuf == NULL || mbuf->header == NULL ) {
174 if( len > RMR_MAX_XID ) {
179 hdr = (uta_mhdr_t *) mbuf->header;
180 memcpy( hdr->xid, src, len );
188 Allows the user programme to set the xaction (xid) field from a string. The end
189 of string (nil) will be included UNLESS the total length including the end of string
190 would exceed the size of the space in the header for the xaction. The return
191 value is RMR_OK for success and !RMR_OK on failure. Errno will be set
194 extern int rmr_str2xact( rmr_mbuf_t* mbuf, unsigned char const* str ) {
195 int len; // len moved -- we do validate
197 if( str == NULL || mbuf == NULL || mbuf->header == NULL ) {
199 return RMR_ERR_BADARG;
203 if( (len = strlen( (char *) str )) > RMR_MAX_XID-1 ) {
205 return RMR_ERR_OVERFLOW;
208 rmr_bytes2xact( mbuf, str, len+1 );
213 Extracts the transaction bytes from the header and places into a
214 user supplied buffer (dest). The buffer must be at least RMR_MAX_XID
215 bytes in length as this function will copy the entire field (even if
216 the sender saved a shorter "string." If the user supplies a nil poniter
217 as the destination, a buffer is allocated; the caller must free when
218 finished. The buffer will be exactly RMR_MAX_XID bytes long.
220 The return value is a pointer to the buffer that was filled (to
221 the dest buffer provided, or the buffer we allocated). If there is an
222 error, a nil pointer is returned, and errno should suggest the root
223 cause of the issue (invalid message or no memory).
225 extern unsigned char* rmr_get_xact( rmr_mbuf_t* mbuf, unsigned char* dest ) {
228 if( mbuf == NULL || mbuf->xaction == NULL ) {
234 if( (dest = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_XID )) == NULL ) {
240 memcpy( dest, mbuf->xaction, RMR_MAX_XID );
246 Extracts the meid (managed entity) from the header and copies the bytes
247 to the user supplied area. If the user supplied pointer is nil, then
248 a buffer will be allocated and it is the user's responsibilty to free.
249 A pointer is returned to the destination memory (allocated or not)
250 for consistency. If the user programme supplies a destination it is
251 the responsibility of the programme to ensure that the space is large
254 extern unsigned char* rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest ) {
259 if( mbuf == NULL || mbuf->header == NULL ) {
265 if( (dest = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID )) == NULL ) {
271 hdr = (uta_mhdr_t *) mbuf->header;
272 memcpy( dest, hdr->meid, RMR_MAX_MEID );
277 // ------------------- trace related access functions --------------------------------------
279 The set_trace function will copy the supplied data for size bytes into the
280 header. If the header trace area is not large enough, a new one will be allocated
281 which will cause a payload copy based on the msg->len value (if 0 no payload
284 The return value is the number of bytes actually coppied. If 0 bytes are coppied
285 errno should indicate the reason. If 0 is returned and errno is 0, then size
286 passed was 0. The state in the message is left UNCHANGED.
288 Regardless of action taken (actual realloc or not) the caller's reference to mbuf
289 is still valid follwing the call and will point to the correct spot (same tp
290 buffer if no realloc needed, or the new one if there was).
292 extern int rmr_set_trace( rmr_mbuf_t* msg, unsigned const char* data, int size ) {
294 rmr_mbuf_t* nm; // new message if larger is needed
296 void* old_tp_buf; // if we need to realloc, must hold old to free
309 hdr = (uta_mhdr_t *) msg->header;
315 len = RMR_TR_LEN( hdr );
317 if( len != size ) { // different sized trace data, must realloc the buffer
318 nm = rmr_realloc_msg( msg, size ); // realloc with changed trace size
319 old_tp_buf = msg->tp_buf; // hold to repoint new mbuf at small buffer
320 old_hdr = msg->header;
322 msg->tp_buf = nm->tp_buf; // reference the reallocated buffer
323 msg->header = nm->header;
324 msg->id = NULL; // currently unused
325 msg->xaction = nm->xaction;
326 msg->payload = nm->payload;
328 nm->tp_buf = old_tp_buf; // set to free; point to the small buffer
329 nm->header = old_hdr; // nano frees on hdr, so must set both
332 hdr = (uta_mhdr_t *) msg->header; // header WILL be different
333 len = RMR_TR_LEN( hdr );
336 memcpy( TRACE_ADDR( hdr ), data, size );
343 Returns a pointer (reference) to the trace data in the message. If sizeptr
344 is supplied, then the trace data size is assigned to the referenced
345 integer so that the caller doesn't need to make a second call to get the
348 CAUTION: user programmes should avoid writing to the referenced trace
349 area (use rmr_set_trace() to avoid possible data overruns. This
350 function is a convenience, and it is expected that users will
351 use the trace data as read-only so as a copy is not necessary.
353 extern void* rmr_trace_ref( rmr_mbuf_t* msg, int* sizeptr ) {
354 uta_mhdr_t* hdr = NULL;
357 if( sizeptr != NULL ) {
358 *sizeptr = 0; // ensure reset if we bail
366 if( (size = RMR_TR_LEN( hdr )) <= 0 ) {
370 if( sizeptr != NULL ) {
374 return (void *) TRACE_ADDR( hdr );
378 Copies the trace bytes from the message header into the buffer provided by
379 the user. If the trace data in the header is less than size, then only
380 that number of bytes are copied, else exactly size bytes are copied. The
381 number actually copied is returned.
383 extern int rmr_get_trace( rmr_mbuf_t* msg, unsigned char* dest, int size ) {
384 uta_mhdr_t* hdr = NULL;
391 if( size <= 0 || dest == NULL ) {
396 if( (n2copy = size < RMR_TR_LEN( hdr ) ? size : RMR_TR_LEN( hdr )) <= 0 ) {
400 memcpy( dest, TRACE_ADDR( hdr ), n2copy );
406 Returns the number of bytes currently allocated for trace data in the message
409 extern int rmr_get_trlen( rmr_mbuf_t* msg ) {
418 return RMR_TR_LEN( hdr );
422 Returns the string in the source portion of the header. This is assumed to be
423 something that can be used for direct sends (hostname:port). Regardless, it
424 will be a nil terminated, ascii string with max of 64 characters including
425 the final nil. So, the user must ensure that dest is at least 64 bytes.
427 As a convenience, the pointer to dest is returned on success; nil on failure
430 extern unsigned char* rmr_get_src( rmr_mbuf_t* msg, unsigned char* dest ) {
431 uta_mhdr_t* hdr = NULL;
440 zt_buf_fill( dest, hdr->src, RMR_MAX_SRC );
447 Returns the string with the IP address as reported by the sender. This is
448 the IP address that the sender has sussed off of one of the interfaces
449 and cannot be guarenteed to be the acutal IP address which was used to
450 establish the connection. The caller must provide a buffer of at least
451 64 bytes; the string will be nil terminated. A pointer to the user's buffer
452 is returned on success, nil on failure.
454 extern unsigned char* rmr_get_srcip( rmr_mbuf_t* msg, unsigned char* dest ) {
455 uta_mhdr_t* hdr = NULL;
460 if( dest != NULL && msg != NULL ) {
462 if( HDR_VERSION( msg->header ) > 2 ) { // src ip was not present in hdr until ver 3
464 zt_buf_fill( dest, hdr->srcip, RMR_MAX_SRC );
468 zt_buf_fill( dest, hdr->src, RMR_MAX_SRC ); // reutrn the name:port for old messages