generate Add mbuf api funcion to reference to trace dat1
[ric-plt/lib/rmr.git] / src / rmr / common / src / mbuf_api.c
1 // : vi ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4         Copyright (c) 2019 Nokia
5         Copyright (c) 2018-2019 AT&T Intellectual Property.
6
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
10
11            http://www.apache.org/licenses/LICENSE-2.0
12
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 ==================================================================================
19 */
20
21 /*
22         Mnemonic:       mbuf_api.c
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.
26
27         Author:         E. Scott Daniels
28         Date:           8 February 2019
29 */
30
31 #include <stdlib.h>
32 #include <netdb.h>                      // uint* types
33 #include <errno.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <stdio.h>
37 #include <semaphore.h>
38
39 #include "rmr.h"                                // things the users see
40 #include "rmr_agnostic.h"               // agnostic things (must be included before private)
41
42
43 // ---------- some wrappers need explicit copy-in functions, also header field setters -----
44
45 /*
46         Allow the user programme to set the meid in the header.  The meid is a fixed
47         length buffer in the header and thus we must ensure it is not overrun. If
48         the  user gives a source buffer that is too large, we truncate. The return
49         value is the number of bytes copied, or -1 for absolute failure (bad pointer
50         etc.).  Errno is set:
51                 EINVAL id poitner, buf or buf header are bad.
52                 EOVERFLOW if the bytes given would have overrun
53
54 */
55 extern int rmr_bytes2meid( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
56         uta_mhdr_t* hdr;
57
58         if( src == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
59                 errno = EINVAL;
60                 return -1;
61         }
62
63         errno = 0;
64         if( len > RMR_MAX_MEID ) {
65                 len = RMR_MAX_MEID;
66                 errno = EOVERFLOW;
67         }
68
69         hdr = (uta_mhdr_t *) mbuf->header;
70         memcpy( hdr->meid, src, len );
71
72         return len;
73 }
74
75 /*
76         Allows the user programme to set the meid from a string. The end of string
77         (nil) will be included UNLESS the total length including the end of string
78         would exceed the size of the space in the header for the meid.  The return
79         value is RMR_OK for success and !RMR_OK on failure. Errno will be set
80         on error.
81 */
82 extern int rmr_str2meid( rmr_mbuf_t* mbuf, unsigned char const* str ) {
83         int len;                // len moved -- we do validate
84
85         if( str == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
86                 errno = EINVAL;
87                 return RMR_ERR_BADARG;
88         }
89
90         errno = 0;
91         if( (len = strlen( (char *) str )) > RMR_MAX_MEID-1 ) {
92                 errno = EOVERFLOW;
93                 return RMR_ERR_OVERFLOW;
94         }
95
96         rmr_bytes2meid( mbuf, str, len+1 );
97         return RMR_OK;
98 }
99
100
101
102 /*
103         This will copy n bytes from source into the payload. If len is larger than
104         the payload only the bytes which will fit are copied, The user should
105         check errno on return to determine success or failure.
106 */
107 extern void rmr_bytes2payload( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
108         if( src == NULL  ||  mbuf == NULL || mbuf->payload == NULL ) {
109                 errno = EINVAL;
110                 return;
111         }
112
113         errno = 0;
114         mbuf->state = RMR_OK;
115         if( len > mbuf->alloc_len - sizeof( uta_mhdr_t ) ) {
116                 mbuf->state = RMR_ERR_OVERFLOW;
117                 errno = EMSGSIZE;
118                 len = mbuf->alloc_len - sizeof( uta_mhdr_t );
119         }
120
121         mbuf->len = len;
122         memcpy( mbuf->payload, src, len );
123 }
124
125 /*
126         This will copy a nil terminated string to the mbuf payload. The buffer length
127         is set to the string length.
128 */
129 extern void rmr_str2payload( rmr_mbuf_t* mbuf, unsigned char const* str ) {
130         rmr_bytes2payload( mbuf, str, strlen( (char *) str ) + 1 );
131 }
132
133
134 /*
135         Allow the user programme to set the xaction field in the header.  The xaction
136         is a fixed length buffer in the header and thus we must ensure it is not overrun.
137         If the  user gives a source buffer that is too large, we truncate. The return
138         value is the number of bytes copied, or -1 for absolute failure (bad pointer
139         etc.).  Errno is set:
140                 EINVAL id poitner, buf or buf header are bad.
141                 EOVERFLOW if the bytes given would have overrun
142
143 */
144 extern int rmr_bytes2xact( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
145         uta_mhdr_t* hdr;
146
147         if( src == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
148                 errno = EINVAL;
149                 return -1;
150         }
151
152         errno = 0;
153         if( len > RMR_MAX_XID ) {
154                 len = RMR_MAX_XID;
155                 errno = EOVERFLOW;
156         }
157
158         hdr = (uta_mhdr_t *) mbuf->header;
159         memcpy( hdr->xid, src, len );
160
161         return len;
162 }
163
164
165
166 /*
167         Allows the user programme to set the xaction (xid) field from a string. The end
168         of string (nil) will be included UNLESS the total length including the end of string
169         would exceed the size of the space in the header for the xaction.  The return
170         value is RMR_OK for success and !RMR_OK on failure. Errno will be set
171         on error.
172 */
173 extern int rmr_str2xact( rmr_mbuf_t* mbuf, unsigned char const* str ) {
174         int len;                // len moved -- we do validate
175
176         if( str == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
177                 errno = EINVAL;
178                 return RMR_ERR_BADARG;
179         }
180
181         errno = 0;
182         if( (len = strlen( (char *) str )) > RMR_MAX_XID-1 ) {
183                 errno = EOVERFLOW;
184                 return RMR_ERR_OVERFLOW;
185         }
186
187         rmr_bytes2xact( mbuf, str, len+1 );
188         return RMR_OK;
189 }
190
191 /*
192         Extracts the meid (managed equipment) from the header and copies the bytes
193         to the user supplied area. If the user supplied pointer is nil, then
194         a buffer will be allocated and it is the user's responsibilty to free.
195         A pointer is returned to the destination memory (allocated or not)
196         for consistency. If the user programme supplies a destination it is
197         the responsibility of the programme to ensure that the space is large
198         enough.
199 */
200 extern unsigned char*  rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest ) {
201         uta_mhdr_t* hdr;
202
203         if( mbuf == NULL || mbuf->header == NULL ) {
204                 errno = EINVAL;
205                 return NULL;
206         }
207
208         if( ! dest ) {
209                 if( (dest = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID )) == NULL ) {
210                         errno = ENOMEM;
211                         return NULL;
212                 }
213         }
214
215         hdr = (uta_mhdr_t *) mbuf->header;
216         memcpy( dest, hdr->meid, RMR_MAX_XID );
217
218         return dest;
219 }
220
221 // ------------------- trace related access functions --------------------------------------
222 /*
223         The set_trace function will copy the supplied data for size bytes into the
224         header.  If the header trace area is not large enough, a new one will be allocated
225         which will cause a payload copy based on the msg->len value (if 0 no payload
226         data is copied).
227
228         The return value is the number of bytes actually coppied. If 0 bytes are coppied
229         errno should indicate the reason. If 0 is returned and errno is 0, then size
230         passed was 0.  The state in the message is left UNCHANGED.
231 */
232 extern int rmr_set_trace( rmr_mbuf_t* msg, unsigned const char* data, int size ) {
233         uta_mhdr_t*     hdr;
234         rmr_mbuf_t* nm;                 // new message if larger is needed
235         int             len;
236         void*   old_tp_buf;             // if we need to realloc, must hold old to free
237         void*   old_hdr;
238
239         if( msg == NULL ) {
240                 errno = EINVAL;
241                 return 0;
242         }
243
244         errno = 0;
245         if( size <= 0 ) {
246                 return 0;
247         }
248
249         hdr = (uta_mhdr_t *) msg->header;
250         if( !hdr ) {
251                 errno = EINVAL;
252                 return 0;
253         }
254
255         len = RMR_TR_LEN( hdr );
256
257         if( len != size ) {                                                     // different sized trace data, must realloc the buffer
258                 nm = rmr_realloc_msg( msg, size );              // realloc with changed trace size
259                 old_tp_buf = msg->tp_buf;
260                 old_hdr = msg->header;
261
262                 msg->tp_buf = nm->tp_buf;                               // reference the reallocated buffer
263                 msg->header = nm->header;
264                 msg->id = NULL;                                                 // currently unused
265                 msg->xaction = nm->xaction;
266                 msg->payload = nm->payload;
267
268                 nm->tp_buf = old_tp_buf;                                // set to free
269                 nm->header = old_hdr;                                   // nano frees on hdr, so must set both
270                 rmr_free_msg( nm );
271
272                 hdr = (uta_mhdr_t *) msg->header;               // header WILL be different
273                 len = RMR_TR_LEN( hdr );
274         }
275
276         memcpy( TRACE_ADDR( hdr ), data, size );
277
278         return size;
279 }
280
281
282 /*
283         Returns a pointer (reference) to the trace data in the message. If sizeptr
284         is supplied, then the trace data size is assigned to the referenced
285         integer so that the caller doesn't need to make a second call to get the
286         value.
287
288         CAUTION:  user programmes should avoid writing to the referenced trace
289                         area (use rmr_set_trace() to avoid possible data overruns. This
290                         function is a convenience, and it is expected that users will
291                         use the trace data as read-only so as a copy is not necessary.
292 */
293 extern void* rmr_trace_ref( rmr_mbuf_t* msg, int* sizeptr ) {
294         uta_mhdr_t*     hdr = NULL;
295         int size = 0;
296
297         if( sizeptr != NULL ) {
298                 *sizeptr = 0;                                   // ensure reset if we bail
299         }
300
301         if( msg == NULL ) {
302                 return NULL;
303         }
304
305         hdr = msg->header;
306         if( (size = RMR_TR_LEN( hdr )) <= 0 ) {
307                 return NULL;
308         }
309
310         if( sizeptr != NULL ) {
311                 *sizeptr = size;
312         }
313
314         return (void *) TRACE_ADDR( hdr );
315 }
316
317 /*
318         Copies the trace bytes from the message header into the buffer provided by
319         the user. If the trace data in the header is less than size, then only
320         that number of bytes are copied, else exactly size bytes are copied. The
321         number actually copied is returned.
322 */
323 extern int rmr_get_trace( rmr_mbuf_t* msg, unsigned char* dest, int size ) {
324         uta_mhdr_t*     hdr = NULL;
325         int n2copy = 0;
326
327         if( msg == NULL ) {
328                 return 0;
329         }
330
331         if( size <= 0 || dest == NULL ) {
332                 return 0;
333         }
334
335         hdr = msg->header;
336         if( (n2copy = size < RMR_TR_LEN( hdr ) ? size : RMR_TR_LEN( hdr )) <= 0  ) {
337                 return 0;
338         }
339
340         memcpy( dest, TRACE_ADDR( hdr ), n2copy );
341
342         return n2copy;
343 }
344
345 /*
346         Returns the number of bytes currently allocated for trace data in the message
347         buffer.
348 */
349 extern int rmr_get_trlen( rmr_mbuf_t* msg ) {
350         uta_mhdr_t*     hdr;
351
352         if( msg == NULL ) {
353                 return 0;
354         }
355
356         hdr = msg->header;
357
358         return RMR_TR_LEN( hdr );
359 }
360
361 /*
362         Returns the string in the source portion of the header. This is assumed to be
363         something that can be used for direct sends (hostname:port). Regardless, it
364         will be a nil terminated, ascii string with max of 64 characters including
365         the final nil. So, the user must ensure that dest is at least 64 bytes.
366
367         As a convenience, the pointer to dest is returned on success; nil on failure
368         with errno set.
369 */
370 extern unsigned char* rmr_get_src( rmr_mbuf_t* msg, unsigned char* dest ) {
371         uta_mhdr_t*     hdr = NULL;
372
373         if( msg == NULL ) {
374                 errno = EINVAL;
375                 return NULL;
376         }
377
378         if( dest != NULL ) {
379                 hdr = msg->header;
380                 strcpy( dest, hdr->src );
381         }
382
383         return dest;
384 }
385
386 /*
387         Returns the string with the IP address as reported by the sender. This is
388         the IP address that the sender has sussed off of one of the interfaces
389         and cannot be guarenteed to be the acutal IP address which was used to
390         establish the connection.   The caller must provide a buffer of at least
391         64 bytes; the string will be nil terminated. A pointer to the user's buffer
392         is returned on success, nil on failure.
393 */
394 extern unsigned char* rmr_get_srcip( rmr_mbuf_t* msg, unsigned char* dest ) {
395         uta_mhdr_t*     hdr = NULL;
396         char*   rstr = NULL;
397
398         errno = EINVAL;
399
400         if( dest != NULL && msg != NULL ) {
401                 hdr = msg->header;
402                 if( HDR_VERSION( msg->header ) > 2 ) {          // src ip was not present in hdr until ver 3
403                         errno = 0;
404                         strcpy( dest, hdr->srcip );
405                         rstr = dest;
406                 } else  {
407                         errno = 0;
408                         strcpy( dest, hdr->src );                               // reutrn the name:port for old messages
409                         rstr = dest;
410                 }
411         }
412
413         return rstr;
414 }